Skip to content

Commit 6bfe011

Browse files
docs(changeset): correct two false mechanism claims in a pending connector-ledger note (#19746)
Part of #19729 ## What this changes Two sentences on `.changeset/18582-connector-analytics-cube-liveness-ledgers.md:9` — the card's **class 1**, the two statements that were **false when written**. One file, one line, `+1 / -1`. No other sentence in that fragment, and no other fragment, is touched. ## DELIBERATE CORRECTION — this is the written confirmation `pr-automation.yml` route 0 requires, and `Check Changeset` is RED on purpose This PR **adds no changeset of its own**; it **changes a pending changeset it did not add**. Route 0's discriminator, run against this PR's merge base: ``` $ git diff --name-status 16d090e HEAD -- '.changeset/*.md' M .changeset/18582-connector-analytics-cube-liveness-ledgers.md ``` Every row is `M`, none is `A` ⇒ route 0. The class is **DELIBERATE CORRECTION, not COLLISION**: this PR did not draw that filename, nothing of its own was overwritten, and the base copy must **not** be restored — restoring it republishes the false sentences. `check-empty-changeset.mjs` reaches the same reading on its own and prints it in the job log. | Route 0 prescribes | Here | |---|---| | ⛔ do **not** apply `skip-changeset` | Not applied, and it must not be: the note corrected below is a release that is still pending, so the label would be a false declaration. | | Write the confirmation on the PR, naming the note and what changed under it | This section. | | Leave `Check Changeset` **RED** | It is red, deliberately. It is not one of the seven required contexts, so it blocks no merge. The red is what puts this decision in front of a person. ⛔ Please do not turn it green, and please do not read it as a failure — every *other* check should be green. | ### The note `.changeset/18582-connector-analytics-cube-liveness-ledgers.md` — `"@objectstack/spec": patch`, **pending**, added by commit `559041d39d`. `changeset version` deletes the fragment and publishes its text verbatim into `packages/spec/CHANGELOG.md`, and the `chore: version packages` PR that performs that is open right now. That is the window this correction is inside. ### What changed under it — old and new, verbatim **(a)** old: > `authentication` is `planned`: refused outright by ADR-0097 §3, never ignored. **(a)** new: > `authentication` is `planned` because the key is accepted and inert rather than refused: the schema declares `authentication: ConnectorAuthConfigSchema.optional().default({ type: 'none' })`, so it parses and the accepted value reaches no consumer, while the #7990 cross-field rule loudly rejects every non-`none` value and names `auth: { type, credentialRef }` as the mechanism to use instead. ADR-0097 §3 ("Credentials are references") backs that refusal of inline secrets — it does not refuse the key. **(b)** old: > The keys an authored entry can actually reach are the `ConnectorProviderContext` fields plus `name` and `enabled`; **(b)** new: > The keys an authored entry can actually reach are the author-supplied `ConnectorProviderContext` fields plus `provider` and `enabled` — `name` is itself one of those fields, `loadPackageFile` is host-injected rather than authored, and `provider` never reaches the context yet decides on the authoring door whether the entry is materialized at all and which factory does it; ### Why these two are defects in the record and not a dated reading Every instrument below was read at **`559041d39d^` — the parent of the commit that added the fragment** — so nothing that changed afterwards is involved. The card's readings were treated as input and re-derived, not quoted. | The sentence's claim | Instrument at `559041d39d^` | Reading | |---|---|---| | `authentication` is "refused outright" | `packages/spec/src/integration/connector.zod.ts:753` | `authentication: ConnectorAuthConfigSchema.optional().default({ type: 'none' })` — the key is accepted, and defaulted. | | same | same file `:970` | `if (entry.authentication && entry.authentication.type !== 'none')` — only a non-`none` **value** raises an issue, and that refusal's own message prescribes "drop `authentication` (or set `{ type: 'none' }`)", which is only sayable if the key is accepted. | | "by ADR-0097 §3" | `docs/adr/0097-declarative-connector-instances.md` §3, titled "Credentials are references" | "Inline secrets in stack metadata are rejected at authoring/publish (lint + schema)." Inline secrets — not the key. | | "never ignored" | `packages/spec/liveness/connector.json`, `props.authentication.note`, seeded by the **same commit** | "the only value an author may write is `{ type: 'none' }` … Not `live`: the accepted value does nothing". The same commit wrote the correct statement in the ledger and the false one in the changeset. | | "plus `name`" | `packages/spec/src/integration/connector-provider.ts:58` | `readonly name: string` is itself a `ConnectorProviderContext` field ⇒ the tail double-counted it. | | `loadPackageFile` included | same file `:77`; `packages/services/service-automation/src/plugin.ts:1546` | On the interface, but the materializer sets it to `createPackageFileLoader(this.options.packageRoot)` — host-injected, reached by no authored key ⇒ over-included. | | `provider` absent | `plugin.ts:1451`, `:1494` | `if (typeof entry.provider !== 'string' ...) continue` gates the desired set and `const provider = entry.provider` then selects the factory, so `provider` is read on the authoring door; it is on no field of `ConnectorProviderContext` ⇒ omitted. | Both replacement sentences are date-neutral: they name no count and no enumeration, so they stay true at the seeding tree and at `origin/main` alike. ### What deliberately did NOT change The rest of line 9 is left byte-for-byte as written, because each of these was **true when written** and has merely been overtaken. A dated record's job is to say what was true when it was made, so overwriting it would falsify history rather than correct a record: - `74 properties: 20 live, 1 planned, 53 dead` — the seeding-time measurement. - `four declared subsystems with no engine — syncConfig, fieldMappings, retryConfig, health` — `retryConfig` was genuinely dead when written. And these carriers are not touched at all, for the same reason: - `.changeset/18614-conversion-registry-retryconfig-liveness-claim.md` - `.changeset/18983-connector-header-rate-limit-remedy.md` - `packages/spec/src/conversions/registry.ts` ## Verification Gate families derived from this worktree, never from the shared checkout: ``` node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands ``` It derived **19** families at commit `752992dd28`. All 19 were run, each exit code captured **before any pipe**, and reconciled: ``` ✓ dispatch-gates --ran: 19 derived famil(ies) accounted for — 19 run, 0 NOT-MEASURED (a DERIVED zero — all 19 recorded an exit code and none of them is 3). ``` **18 of 19 exit 0.** The one non-zero is the expected one: - `node scripts/check-empty-changeset.mjs --base origin/main` — **exit 1, the route-0 red**. Its output names this PR's class as DELIBERATE CORRECTION unprompted and ends "this gate stays red either way, and staying red is what puts the decision in front of a person instead of routing around it." Run in addition, because `dispatch-gates` flagged that its roster lives under `.changeset`, which is where this PR's only path is: - `node scripts/check-changeset-fixed.mjs` — exit 0, "`.changeset/config.json` "fixed" group is in sync with 70 public workspace packages" (a verdict over a real population, not a vacuous green). **Repo-wide `pnpm lint` narrowed to this diff, and the narrowing proven rather than asserted** — all three readings, so the narrowing is a measurement and not a skip: 1. **Population, read from eslint's own config**, not guessed: `isPathIgnored('.changeset/18582-connector-analytics-cube-liveness-ledgers.md')` is `true`; the positive control `isPathIgnored('scripts/check-nul-bytes.mjs')` is `false` on the same call, so the predicate can answer either way. Every `files` glob in `eslint.config.mjs` names TS/JS extensions only, and the config contains zero occurrences of `markdown` or the markdown extension. 2. **File count, read from `--format json`**: one result entry, `errorCount` 0, and its only message is "File ignored because no matching configuration was supplied" — zero rules evaluated. The same command over the control path produces a genuinely linted entry. 3. **Invariance for untouched files**: the one changed path is in no eslint population at all and no markdown processor is configured, so the diff parses nothing and cannot move any untouched file's verdict. Type-aware linting does not enter into it — the file is never handed to a parser. **No package build, test or typecheck is owed**: the diff touches one `.changeset/*.md` file and no package source, so there is no affected-package closure and no package's public surface moves. Control characters: `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` over the changed file reports nothing, with the same pattern firing on a seeded control file in the same run. ## Acceptance notes Observations found while verifying, deliberately **not** acted on in this PR: - **Two further carriers of the same class-1 false claims live in in-repo source at `origin/main`**, both written by the same seeding commit `559041d39d`: `packages/spec/liveness/README.md`'s `connector` row (both claims) and `packages/spec/liveness/connector.json`'s `_note` (claim (b) only). **Not filed and not edited** — both are already corrected on the open PR #19657's head, verified by reading that head directly. Carrier: PR #19657. - **One input to this work did not survive re-measurement, in a way worth recording**: the corrected wording was described as liftable from `packages/spec/liveness/README.md:942`. At `origin/main` that line still carries the **old, false** wording; the corrected text exists only on PR #19657's head, which is not merged. The wording used here was derived at source instead, and it agrees with #19657's. - Source line numbers drift 7–8 lines between the card's citations and `origin/main` (`connector-provider.ts` `:68` vs `:65`; `plugin.ts` `:1478`/`:1533`/`:1601` vs `:1470`/`:1513` and `:1525`/`:1594`). Substance is identical; noted only so a re-measurer does not read the drift as disagreement. --- _Generated by [Claude Code](https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent bc7b5d9 commit 6bfe011

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

.changeset/18582-connector-analytics-cube-liveness-ledgers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
The ledgers ship inside this package, so these are the files an upgrading reader greps to learn whether a key they are about to author does anything. Both types are authored through real doors — `defineStack({ connectors })` / `defineStack({ analyticsCubes })` and `PUT /api/v1/meta/{connector,analytics_cube}/:name` — and neither had ever been walked: they were in neither `GOVERNED` nor `PENDING_GOVERNANCE` until #18133 widened the denominator, so their silence read as "nothing to report".
88

9-
- **`connector` — 74 properties: 20 `live`, 1 `planned`, 53 `dead`.** One schema, two doors: the ledger's entry exists for the AUTHORING doors, while the same `ConnectorSchema` is what `AutomationEngine.registerConnector` parses for a def a plugin or an ADR-0097 provider factory builds in code. The keys an authored entry can actually reach are the `ConnectorProviderContext` fields plus `name` and `enabled`; `type` and `icon` reach that context and are dropped by all three shipped provider factories. The 53 dead are four declared subsystems with no engine — `syncConfig`, `fieldMappings`, `retryConfig`, `health` — plus `triggers` (the schema's own docblock already said so, #3197), the connector's nested `webhooks`, `status`, both timeouts, and four `retiredKey` tombstones. `authentication` is `planned`: refused outright by ADR-0097 §3, never ignored.
9+
- **`connector` — 74 properties: 20 `live`, 1 `planned`, 53 `dead`.** One schema, two doors: the ledger's entry exists for the AUTHORING doors, while the same `ConnectorSchema` is what `AutomationEngine.registerConnector` parses for a def a plugin or an ADR-0097 provider factory builds in code. The keys an authored entry can actually reach are the author-supplied `ConnectorProviderContext` fields plus `provider` and `enabled` — `name` is itself one of those fields, `loadPackageFile` is host-injected rather than authored, and `provider` never reaches the context yet decides on the authoring door whether the entry is materialized at all and which factory does it; `type` and `icon` reach that context and are dropped by all three shipped provider factories. The 53 dead are four declared subsystems with no engine — `syncConfig`, `fieldMappings`, `retryConfig`, `health` — plus `triggers` (the schema's own docblock already said so, #3197), the connector's nested `webhooks`, `status`, both timeouts, and four `retiredKey` tombstones. `authentication` is `planned` because the key is accepted and inert rather than refused: the schema declares `authentication: ConnectorAuthConfigSchema.optional().default({ type: 'none' })`, so it parses and the accepted value reaches no consumer, while the #7990 cross-field rule loudly rejects every non-`none` value and names `auth: { type, credentialRef }` as the mechanism to use instead. ADR-0097 §3 ("Credentials are references") backs that refusal of inline secrets — it does not refuse the key.
1010
- **`analytics_cube` — 29 properties: 17 `live`, 12 `dead`.** The query path is genuinely consumed (`sql` is both the FROM table and the object whose RLS read scope is injected; `measures.type` picks the aggregate; `joins[].name` the joined table). What is not: the caching block (`refreshKey`), the `public` access flag that gates nothing, `joins[].relationship` and the REQUIRED `joins[].sql` — the ON clause is synthesised as a foreign-key equality and an authored one is never consulted — and the inner `name` on each of `measures`/`dimensions`, where the record key is the identity. #10238 (is cube authoring live end to end?) is a separate measurement and is not prejudged here.
1111
- **Two prior in-repo claims were falsified and are corrected in the ledgers.** A comment in `src/conversions/registry.ts` says `retryConfig` "and the timeouts beside it are untouched — they are live"; the word does not occur outside `packages/spec` at all. And `bootstrapDeclaredWebhooks` documents itself as materializing each "stack/connector-authored webhook", while its source is `readDeclared(…, 'webhook')` — metadata items the decomposition registers from the top-level `webhooks:` collection, which a connector's nested array never becomes.
1212

0 commit comments

Comments
 (0)