Skip to content

Disclosure first: this is not a pre-registration


rank: decision outranks: [] doc_id: PTV-DEC-0019 title: N8N-27 exit condition — what closes the store sweep, and what it knowingly leaves unswept date: 2026-08-17 status: closed owner: petrova-codes scaffold: PTV-SCF-0001 phase: P4 supersedes: none depends_on: docs/decisions/2026-08-17-what-counts-as-a-credential-store.md

Section titled “rank: decision outranks: [] doc_id: PTV-DEC-0019 title: N8N-27 exit condition — what closes the store sweep, and what it knowingly leaves unswept date: 2026-08-17 status: closed owner: petrova-codes scaffold: PTV-SCF-0001 phase: P4 supersedes: none depends_on: docs/decisions/2026-08-17-what-counts-as-a-credential-store.md”

Disclosure first: this is not a pre-registration

Section titled “Disclosure first: this is not a pre-registration”

PTV-DEC-0018 was written before the sweep, deliberately, so the store boundary could not be settled while reading results. This document was not. The corrected multi-source pass finished at 13:56 and this was written afterwards, so the single most corruptible operation — grading a result against a definition written after seeing it — is available here and must be blocked explicitly rather than assumed away.

How it is blocked: every clause below is traceable to PTV-DEC-0018 §“What the sweep must record”, which was pre-registered — the repo denominator with itemised skips, per-store class and reachability, multi-source resolutions, and what the instrument cannot see. Nothing here is a criterion invented to fit hits-org-ms.tsv. Where this document adds a requirement, it comes from PTV-FND-0042 (per-class positive control), which is a method rule and not a result.

The reader should still treat the ordering as a defect in the record. It is recorded rather than repaired because repairing it is not possible after the fact.

By reference to PTV-DEC-0018 §“The definition” and its in-scope/out-of-scope tables. Not widened here. A boundary change requires a superseding decision doc (MR-7), not a clause in the exit condition of the sweep it governs.

scanned-org-ms.tsv 465 rows one row per repo attempted
ok 417
empty 48 default branch has no files at depth 1
clone-fail 0
hits-org-ms.tsv 10 rows multi-source class, corrected pattern
repos with hits 2 rocky-hq/console, grace-hq/rocky

The earlier all-seven-class pass over the same 465 (scanned-org.tsv) recorded ok=416, empty=48 (identical set, verified by diff), clone-fail=1 (v01t-io/integration-hub).

The 465 is a contested population and stays contested

Section titled “The 465 is a contested population and stays contested”

PTV-DEC-0018 §“The denominator is already unstable” records two enumerations that disagree: 30 orgs / 465 repos (PTV-FND-0032) against 40 orgs / 458 in-org / 524 accessible. 465 is the PTV-FND-0032 population, reused here so the two figures are comparable, and the reconciliation is still unmeasured.

Any coverage figure in this sweep is therefore a fraction of a number that has not been reconciled, and must be read that way. Reconciling it is part of N8N-27; it is not waved through by this document.

Not summarised — PTV-DEC-0018 requires skips itemised and reasoned, because the store-denominator error came from three known stores with no record of how “known” was established.

  • choco-hq (42): black-ice, choco-analytics, choco-assistant, choco-auth, choco-billing, choco-cli, choco-compiler, choco-edge-gateway, choco-forge, choco-gateway, choco-gitops, choco-infra, choco-ledger, choco-mcp-server, choco-observability, choco-pipes, choco-sdk-go, choco-sdk-python, choco-sdk-ts, choco-search, choco-sync, choco-ui-kit, choco-vault, choco-verifier, choco-web, choco-webhooks, echo-chamber, fork-node, frontend-template, golden-press, library-template, null-route, service-template, the-boiler-room, the-cocoa-bean, the-compiler, the-ledger, the-recipe-book, the-river, the-vault, vest-node, zero-point
  • other (6): clari-tools/web, Dev4rno/featr.io-server, rocky-hq/algo, v01t-io/ci-cd-pipelines, v01t-io/helm-charts, v01t-io/kubernetes-manifests
  • clone-fail (1, first pass only): v01t-io/integration-hub

Reason, uniform: git clone --depth 1 of the default branch produced a tree with no files outside .git. That is consistent with an unpushed placeholder repo, which is what 42 of 48 being choco-hq scaffolding suggests — but the sweep measured emptiness at depth 1 on one branch, not emptiness of the repository.

Two of them are named choco-vault and the-vault. Nothing about the name is evidence, and nothing about the sweep clears them either. They are unswept repositories whose names are in the class being hunted, and that is exactly the combination this document refuses to round to zero.

Stated as limits, per PTV-DEC-0018 §4 — a limit, not a clean negative.

ResidualWhy the instrument cannot see it
Non-GitHub codeThe population is gh-enumerated; anything not in an accessible org or user account is outside it
Private gistsNever enumerated by any pass
Non-default branches--depth 1 on the default branch only; a store on a feature branch is invisible
The 48 emptiesAbove. Includes two vault-named repos
Vendored dependencies--exclude-dir=node_modules,vendor,dist,.next,build,.venv — a store inside a dependency is excluded by construction
Excluded test trees--exclude-dir=tests,test,e2e,fixtures,__tests__ and the noise pattern. PTV-FND-0041 removed real test-fixture noise this way; the cost is that a store in a test tree is now unseeable
Local worktrees absent from the org listMeasured instance: v01t-io/meta, which holds the vendored rocky-hq source behind the /migration/state/ noise, is not in org-repos.txt — the org has meta-* repos, no bare meta. The local set is not a subset of the org set, in either direction
Credentials written into a database through a UIReading code finds stores declared in code (PTV-DEC-0018 §4)
A store fetched from a service whose name is itself a secretSame clause
GitHub Actions secret valuesStructurally unsweepable — write-only by design (PTV-FND-0033 corollary). Names enumerate across 465 repos; no value read path exists for anyone
Vercel sensitive variable namessensitive_names.py died on its first call with HTTP Error 403, output contains zero SENSITIVE lines. ~63 project-level declarations exist per sweep_vercel2.py’s incidental count. Unmeasured, not empty (PTV-FND-0042)

From n8n27/control-filter.sh (PTV-FND-0042). A class with no known-true input anywhere in the estate cannot be validated, and its zero is not a measured zero.

ClassControlStatus
multi-sourcerocky-hq/console:src/lib/n8n-client.ts:10 + 3 siblingscontrolled, corrected pattern, re-run complete
app-vaultsrc/lib/vault/store.ts, crypto.ts, src/app/api/vault/route.tscontrolled, retained retrospectively in hits-org.tsv
db-credentialchoco-hq/choco-hq:infrastructure/migrations/000003_api_keys_and_sessions.up.sql:5, skyflow-blue/infrastructure:migrations/001_core_schema.sql:153controlled
secret-filenone existsUNCONTROLLED
mounted-secretnone existsUNCONTROLLED
hardcoded-keynone existsUNCONTROLLED
runtime-fetchnone existsUNCONTROLLED

The four uncontrolled classes carry 123 + 29 + 10 + 1 = 163 of the 240 candidate hits in the all-seven pass. That is the majority of the sweep’s output sitting behind an unvalidated instrument, and it is the reason this document exists rather than a closure note.

N8N-27 closes when all four hold:

  1. Denominator recorded — 465 with the 48 skips itemised and the population named, plus a stated position on the 465-vs-458-vs-524 disagreement.
  2. Per-class control status recorded — every class either has a passing positive control or the label UNCONTROLLED. Classes may close uncontrolled; they may not close silently uncontrolled.
  3. Residual stated — the table above, as limits.
  4. Confirmed stores listed with reachability — per store: repo, path, class, credential held if determinable, and whether it is reachable in a live deployment or only in principle (PTV-DEC-0018 §2). Candidates are not promoted by count (PTV-FND-0041).

N8N-27 does not close because a scan finished, because a count is small, or because the confirmed store list is a single entry. As measured today, 1, 2 and 3 are satisfied by this document plus PTV-FND-0042; 4 is satisfied only for the classes that have controls.

N8N-01 and N8N-03 become schedulable when the closure test passes and this decision is countersigned — not before. The mint remains the structural block that nothing in this item routes around: no store enumeration produces a replacement credential.

N8N-30 (rocky-console’s vault holds GitHub and Anthropic credentials no inventory has counted, PTV-FND-0041 §Consequences 4) stays outside this close-out rather than being absorbed into it.

Amendment — 2026-08-17, before countersign (PTV-FND-0044)

Section titled “Amendment — 2026-08-17, before countersign (PTV-FND-0044)”

Appended rather than edited in place (MR-7). The clauses above stand as written; this records what has been measured since.

On the disclosure above, and why it is the mechanism rather than an apology. PTV-DEC-0018 was pre-registered precisely so that a document like this one could be written after the run without the grading being shaped by it. The definition of a store, the requirement to itemise skips, and the requirement to state the residual all existed before any result did; only the prose grading them came after. That is pre-registration working as intended. A disclosure of the ordering is what lets a reader confirm it, and it should be read as the control holding, not as a defect being confessed.

Per-class control status — four rows superseded. secret-file, mounted-secret, hardcoded-key and runtime-fetch are no longer UNCONTROLLED. Synthetic controls (n8n27/control-synthetic.sh) plant one instance of each class; all four fire. Their recall against ten realistic in-scope variants is 4 of 10, with the six misses named individually in PTV-FND-0044. Read every negative in these classes as 4/10 recall against ten named variants, not as absence.

Residual — the 48 empties row is discharged. All 48 return 409 Git Repository is empty with size == 0 and no refs of any kind, so they are empty at ref level and not merely on the default branch. choco-vault and the-vault included; both were created and never written to (one-second create/push signatures, and choco-vault is archived).

Residual — a new row. Pattern recall is bounded by naming convention. Six of ten probes miss because the patterns enumerate vendors and spellings rather than matching values: Kubernetes secretName, HashiCorp vault kv get, Azure Key Vault, .env.vault, docker-compose secrets:, and a lower-case SQL read of a table named integration_credentials. Value-matching is omission-resistant; name-matching is lower-confidence by construction (PTV-FND-0044).

Withdrawn. The Vercel sensitive names are not unmeasured. A re-run census gives PROJECTS=72 SENSITIVE_ROWS=63 ERRORS=0, matching PTV-FND-0037 exactly. PTV-FND-0042’s claim to the contrary is retracted in PTV-FND-0044; the sensitive_names.py 403 is a real defect in that script and nothing more.

Closure test status after this amendment: clauses 1, 2 and 3 hold. Clause 4 — confirmed stores listed with reachability — remains open for every class, and is the next move.

Amendment — 2026-08-17, before countersign (PTV-FND-0052)

Section titled “Amendment — 2026-08-17, before countersign (PTV-FND-0052)”

Appended, not edited (MR-7). Records the reachability pass the previous amendment named as the next move.

Clause 4, repo layer: discharged. All 29 repos carrying candidate hits now have a measured deployment verdict, from three instruments — GitHub facts, platform project existence keyed on the git link rather than the project name, and CI deploy paths read rather than counted.

DEPLOYED 10 repo(s) 104 hit(s)
UNDETERMINED 1 repo(s) 18 hit(s)
UNBUILT 18 repo(s) 118 hit(s)

Clause 4, store layer: still open. 118 of 240 candidates are code copies under PTV-FND-0043 and cannot be stores. The remaining 122 have not yet been adjudicated hit by hit into store / not a store, nor had the credential each holds determined. Clause 4 closes on that list, not on this triage.

Residual — two rows added, both bounds on this pass.

ResidualWhy the instrument cannot see it
Deployments with no git link35 of 65 Railway services have source.repo == null (CLI- or image-deployed). “No platform link” is therefore not “not deployed”; smo1-io/purr-api is the measured instance and is recorded UNDETERMINED rather than resolved
Hosts outside Vercel, Railway and GitHub ActionsUNBUILT is negative across exactly those three. nestr-tools/perch deploys to a Kubernetes cluster none of them enumerate — a measured instance of a host outside the instrument, not a hypothetical

A boundary question raised and deliberately not answered. sparki-tools/mobile-ios is reachable as a client binary. The definition in PTV-DEC-0018 says “reachable by a running deployment” and does not separate server-side from client-side; its 26 hits ship to every install. Widening or splitting that clause requires a superseding decision doc, so it is recorded here as an open boundary question and the hits are counted under the definition as written.

A guard limitation, recorded against the hardening this document relies on. The PTV-FND-0044 guards exit non-zero on empty or traceback-only output. They passed on a run whose homepage column was shifted by one field for 18 of 29 rows, because the output was neither empty nor a traceback. Shape guards (arity, column types) are now asserted alongside. Read every prior “guard ok” as the command produced output, never as the output is correct.

Amendment — 2026-08-17, before countersign (PTV-FND-0046, PTV-DEC-0020)

Section titled “Amendment — 2026-08-17, before countersign (PTV-FND-0046, PTV-DEC-0020)”

Appended, not edited (MR-7). Two verdicts in the previous amendment’s table are corrected, and one exclusion is proposed.

Corrected verdicts. Both move toward unbuilt.

was (PTV-FND-0045) now (PTV-FND-0046)
DEPLOYED 10 repo(s) 104 hit(s) 9 repo(s) 98 hit(s)
UNDETERMINED 1 repo(s) 18 hit(s) 0 repo(s) 0 hit(s)
UNBUILT 18 repo(s) 118 hit(s) 20 repo(s) 142 hit(s)
  • nestr-tools/perch — DEPLOYED → UNBUILT. Every step of deploy.yml is continue-on-error: true and KUBE_CONFIG_STAGING does not exist; its green Deploy / success run is manufactured by the error swallowing. It has never reached a cluster.
  • smo1-io/purr-api — UNDETERMINED → UNBUILT, on four signals that are not the name: null source, null image, FAILED latest deployment from 2026-03-15 with nothing since, placeholder CI.

The Kubernetes residual row is withdrawn as written. The previous amendment recorded perch as a measured instance of a host outside the instrument. It is not, because it is not a host at all. No repo in the candidate set is confirmed on Kubernetes, and whether the estate runs any cluster is unanswered by every instrument in this item. The residual row survives in weaker form: UNBUILT is still negative across Vercel, Railway and GitHub Actions only, and other hosts remain outside — but no measured instance of one is now claimed.

A recall bound that tightens clause 2. mounted-secret recall measured against real in-estate input, in perch’s tree: 6 of 31 (19%), and all 6 are the default Kubernetes service-account mount. Every mounted-secret zero in this sweep is bounded below by 19%, not by the 4/10 synthetic figure. Clause 2’s per-class status is unchanged in kind — the class remains controlled only synthetically — but its number is now worse and measured.

Residual — one row added, one clarified.

ResidualWhy the instrument cannot see it
A green CI run proves nothingcontinue-on-error on every step yields success from a job in which nothing executed. Any pass keying on run conclusions inherits this across 465 repos of green checkmarks
DNS resolution, demotedNot evidence in either direction. devarno-cloud/casa is DEPLOYED (Vercel host-casa, git-linked) and its declared homepage casa.devarno.cloud is NXDOMAIN. DNS stays in the discharge order as corroboration and may never decide a verdict

skyflow-blue/infrastructure is not a fifth store class. Its two Actions secrets are inside PTV-FND-0032’s complete name-level enumeration (readable=465 noaccess=0), and platform environment variables are excluded by PTV-DEC-0018’s out-of-scope table. Seen, and deliberately excluded. What is new is only that the exclusion assumed such a credential belongs to a deployed application; here it belongs to an unbuilt repo, so nothing pairs the credential with a consumer.

Clause 4 scope narrows, pending PTV-DEC-0020. That decision proposes that a credential shipped to every client install is disclosed, not stored, and is handed to a new item. If countersigned, sparki-tools/mobile-ios’s 26 hits leave this sweep and the store candidate set becomes 72 hits across 8 repos. Until it is countersigned the 26 remain formally in scope and clause 4 cannot close.

How clause 4 must be reported when it does close. Per surviving hit: a verdict and the class it came from; and per class, a confidence — controlled classes at their measured recall, the four synthetic-only classes flagged bounded-below. A single aggregate figure over the surviving set is prohibited: it would launder the uncontrolled classes into the controlled ones, which is the laundering the recall bound exists to prevent.

Amendment — 2026-08-18, before countersign (PTV-FND-0047)

Section titled “Amendment — 2026-08-18, before countersign (PTV-FND-0047)”

Appended, not edited (MR-7). Records the CI-outcome audit that the previous amendment’s guard defect made necessary, and which was named as a precondition of countersigning this document.

The audit is complete. Scoped to the verdicts actually exposed — those resting on reading a workflow body rather than on a platform’s git-link record, which is where the read-the-verb-not-the-guard defect lives. Eight of nine DEPLOYED verdicts rest on a platform project the platform itself reports as linked to the repo, and are not exposed. One rested on CI body reading, and it reversed.

sparki-tools/mobile-ios — DEPLOYED → UNBUILT. No Actions secrets at repo scope or in either environment; six consecutive iOS Deploy failures; latest run’s jobs Deploy to Testing → failure, Deploy to Development → skipped; nothing since 2026-03-15. The perch defect by the opposite route: perch hid failure behind continue-on-error, mobile-ios failed visibly and the instrument was not looking.

Generalisation, recorded as a limit on the instrument rather than a fixed defect: a workflow file states intent; deployment is a fact about execution. All three reversals in this item graded intent as outcome.

PTV-FND-0045 PTV-FND-0046 now (PTV-FND-0047)
DEPLOYED 10 / 104 9 / 98 8 / 72
UNDETERMINED 1 / 18 0 / 0 0 / 0
UNBUILT 18 / 118 20 / 142 21 / 168 (70%)

Clause 4’s adjudication surface is 72 hits across 8 repos: rocky-hq/console, choco-hq/choco-hq, kahn-hq/kahn, sparki-tools/api-engine, traceo-cat/traceo-mcp-server, devarno-cloud/casa, devarno-cloud/landing, Dev4rno/skyflow-client. Reporting form is unchanged from the previous amendment: per-hit verdict plus originating class, per-class confidence, no aggregate.

PTV-DEC-0020 no longer gates this document. It was blocking on 26 unadjudicable client-shipped hits; those hits are unreachable, so the hole it was written to close does not exist. It stands as pre-registration.

Direction flag, carried forward unresolved. Three verdicts have reversed and all three moved toward unbuilt, shrinking the surviving set each time. That is the shape motivated reasoning takes. Each reversal rests on a positive query — continue-on-error plus a missing secret, a FAILED deployment status, six recorded run failures across three empty secret scopes — and none on an argument from silence. The flag stays in the record rather than being resolved, so a reviewer can check the direction rather than take this paragraph for the check.

Appended, not edited (MR-7).

A guard on the surface size itself, added at countersign.

The candidate surface has moved 104 → 98 → 72 across three revisions. Every movement was in one direction, and every one came from a defect found in the reachability instrument. Adjudication now proceeds with a different instrument — the seven class patterns, four of which are controlled only synthetically and whose recall is measured at 19% against real input (PTV-FND-0046).

These two instruments’ error rates do not compose, and the shrinking surface must not be read as convergence. It is the deployment layer becoming more accurate while the detection layer’s bound is unchanged.

Therefore: the number 72 carries no confidence claim. It is the count of candidates that survived reachability triage, not a measured total of stores, and not an upper bound on them — the detection layer’s misses were never in it to begin with. Per-class confidence with no aggregate (previous amendment) guards the store list; this clause guards the surface it is drawn from.

The durable output of this item, for a reader who has only the tables.

A workflow file states intent; deployment is a fact about execution. A CI success is evidence about an exit code and nothing else.

Both reversal routes are instances: nestr-tools/perch hid failure behind continue-on-error; sparki-tools/mobile-ios failed visibly and the instrument was not looking. Opposite routes, one defect.

  • Human countersign — the closure test above is what N8N-27 is measured against, and the residual list is accepted as knowingly unswept

Countersigned by human:alex@devarno.com on 2026-08-18 — restated here from this document’s own prior status: line (countersigned 2026-08-18 — alex@devarno.com), mapped to the recognized open|closed|superseded vocabulary 2026-09-05. No fact about who signed or when is changed.

Unchecked, this decision is open and any claim that N8N-27 is closed is provisional against it.