Skip to content

Commit 7607076

Browse files
os-billclaude
andauthored
fix(spec): register sys_environment_credential in CLOUD_PROVIDED_OBJECT_NAMES (#18851)
Fixes #18309 Clause-②: yes (widening) Scoped to **item 1 of the card only**. Item 2 — grading `sys_tenant_database` under enforce-or-remove — is decision-shaped and is not touched here; `packages/spec/src/cloud/tenant.zod.ts` is unmodified. ## What changed `CLOUD_PROVIDED_OBJECT_NAMES` gains one member, `sys_environment_credential`, plus a named pin test and a `minor` changeset. Three files, 69 insertions, nothing removed and no other member moved — the same shape as PR #17214, which added `sys_package_version`. ## The cloud half is the filer's reading, not a measurement taken here The registration chain — `objects/sys-environment-credential.object.ts` exported through `objects/index.ts`, listed in `tenantObjects` in `manifest.ts`, spread into `manifestService.register({ objects })` by `tenant-plugin.ts` — was read **in the cloud repository at `cb8ee7ff60`** and is carried here on its filer's name. It is not re-checkable from this repo, which is what the list's own header means by "they cannot be conformance-tested from this repo". Nothing in this PR re-took it, and the pin comment and changeset both say so in as many words. What IS measured here is the objectstack half: the contents of the list, the predicate built from it, and the ladder verdict that consumes it. ## Re-taken readings **Reference census, taken on this branch at `d18f7d78a8`** (the card's own count was taken 2026-09-15 and is unchanged): | query | files | |---|---| | `sys_environment_credential` in `*.object.ts` | **0** | | `sys_environment_credential` anywhere tracked | 11 (2 ADRs, 7 `CHANGELOG.md` rename records, and this PR's two spec files) | | `sys_package_version` anywhere tracked (positive control) | 34 | | `sys_definitely_not_real` anywhere tracked (negative control) | 0 | So **no shipped `*.object.ts` references the name**, the card's `priority:p3` grading stands on its stated reason, and nothing here promotes it. **Does the existing pin test redden?** No. `platform-object-names.test.ts` pins the list neither by length nor by full set: it loops `CLOUD_PROVIDED_OBJECT_NAMES` asserting each member resolves and is not declared in this repo — both of which a new member satisfies on arrival — and then pins `sys_license` and the `sys_package*` family **by name**. A member added without a named pin is therefore invisible to the suite, which is exactly the gap the file's own comments say the by-name pins exist to close, so this change adds one in the same style. Suite went 9 tests to 10, green. ## Controls Both legs rebuild `packages/spec` and prove the state reached `dist/` with `scripts/ablation-dist-preflight.mjs` before the reading is allowed to mean anything — `@objectstack/lint` resolves `@objectstack/spec/system` through `exports`, so a verdict taken without rebuilding is a fact about the previous build. Probe: an object declaration whose lookup field targets the name, through `validateObjectReferences`. | name | BEFORE (member ablated out of `dist`) | AFTER (`d18f7d78a8`) | |---|---|---| | **`sys_environment_credential`** (LIT) | `predicate=false`, **1 finding** — `warning:object-reference-unregistered-platform` | `predicate=true`, **0 findings** | | `sys_app`, `sys_environment`, `sys_environment_member`, `sys_license`, `sys_package`, `sys_package_installation`, `sys_package_version` (DARK-A) | `predicate=true`, 0 findings — each | `predicate=true`, 0 findings — each | | `sys_definitely_not_real` (DARK-B) | `predicate=false`, 1 finding | `predicate=false`, 1 finding | | `sys_approval_process` (instrument control) | `predicate=false`, 1 finding | `predicate=false`, 1 finding | | `sys_user` / `crm_deployment` (instrument controls) | 0 findings | 0 findings | The lit control is non-zero and every dark reading is unchanged. Preflight confirmed the marker absent from all 216 built files on the ablated leg and present in 8 on the restored leg; the restore was proven by whole-tree `git status --porcelain` (0 lines) and by `git hash-object` matching the HEAD blob `c10c88f1e0…`. No probe file was left in the repo. **One correction to the card's wording.** The card says "the first shipped reference to it would be refused". The measured verdict is a **`warning`**, not a refusal: rung ④ of `validate-object-references`'s severity ladder is advisory by design, because a third-party package may legitimately provide a platform-prefixed name. `defineStack`'s own hard throw uses a prefix test (`isPlatformObjectName` in `stack.zod.ts`), which accepted the name both before and after this change. So the flip is real and the direction the card describes is right, but what flipped is a diagnostic, not a rejection — the name was never hard-refused, and this PR does not manufacture a refusal to make the stronger reading true. ## The two `merge=os-regen` artefacts do not move `packages/spec/api-surface/system.json` and `packages/spec/export-origins/system.json` were pre-declared on the claim as regeneration targets. Measured: they record export **names and origins**, not values, so the list's contents are invisible to them — `git grep -c sys_package` over both directories returns 0 hits. The repo's own generator wrapper confirms it: `pnpm --filter @objectstack/spec check:generated` reports **all 15 generated artifacts up to date**, `check:api-surface` and `check:export-origins` among them, so `--fix` had nothing to regenerate. Neither file is hand-edited and neither is in this diff. PR #17214 touched the same three-file set for the same reason. ## Verification Run at `d18f7d78a8` unless noted. - `pnpm --filter @objectstack/spec build` — green (through the shared verify lock) - `pnpm --filter @objectstack/spec test` — **487 files / 14055 tests passed** - `pnpm --filter @objectstack/spec typecheck` — green (incl. `check:scripts-typecheck`, `check:test-typecheck`) - `pnpm --filter @objectstack/lint test` — **104 files / 3879 passed, 5 skipped**, after building lint's dependency closure. The first run showed 41 files failing to collect on `@objectstack/formula` / `@objectstack/sdui-parser` having no `dist/`; that is unbuilt-closure state, not this diff, and it cleared on `pnpm --filter '@objectstack/lint^...' build`. - `pnpm --filter @objectstack/spec check:generated` — all 15 up to date - Gate families: `check:nul-bytes`, `check:merge-driver`, `check:cross-package-test-inputs`, `check:test-source-alias`, `check:published-files`, `check:dts-closure`, `check:type-check-coverage`, `check:entry-nameability`, `check:browser-reachable-entries`, `check:dual-source-exports`, `check:exported-any`, `check-empty-changeset`, `check-adr-0087-registration`, `check-platform-object-tenancy-census`, `check-spec-docblock-symbol-anchors`, `check-comment-mask-adoption`, `check-comment-mask-corpus`, `check-keyed-text-bounds` — all exit 0. - eslint, narrowed and declared: `eslint --no-inline-config` over the diff's two lintable files, **0 errors / 0 warnings**, file count read from `--format json` (2 — the third changed path is a `.changeset/*.md`, which no `files` entry in `eslint.config.mjs` matches). The narrowing is safe because this config runs **no type-aware linting** — `eslint.config.mjs:328` records "no `parserOptions.project`, no typed `@typescript-eslint` rules", and there is no `projectService` anywhere in it — so each file's verdict is a function of that file alone and a two-file diff cannot move an untouched file's verdict. The repo-wide run remains CI's. NOT MEASURED, with reasons: - `check:type-check-debt` exited **3**, which the script itself prints as `PREREQUISITE NOT MET` — it needs the whole-repo build closure that `lint.yml` builds before the step. Its own text: "This is NOT a pass and NOT a finding: nothing was measured." Recorded as unmeasured, not as red. - `check-changeset-no-major.mjs` ran green but reports its **level axis NOT APPLICABLE** locally: it reads the clause-② declaration from a `pull_request` payload, which a local run has not got. The axis gets its input once this PR exists. - `dispatch-gates --ran` reconciles 27 of 81 derived families run locally. The remainder are checker `--self-test` invocations and repo-wide scans that CI owns. ## Acceptance notes Observations from the surrounding code, filed nowhere and deliberately not fixed here: - `PLATFORM_OBJECTS_BY_PACKAGE` carries a per-package conformance scan that reddens on drift; `CLOUD_PROVIDED_OBJECT_NAMES` has no such half by construction, so every member it holds rests on a cross-repo reading with no local ratchet behind it. That is the documented design, not a defect, and it is why this PR adds a by-name pin rather than claiming conformance. Noted, not filed — no PR or person is queued against this file. - ADR-0007's inventory table lists `sys_environment_credential` as existing while the registry that decides whether a reference resolves said nothing registers it. The two now agree. Noted, not filed: an ADR stating a true fact about the cloud runtime is not a contract violation, and nothing in this repo consumed the ADR table as metadata. ## Ownership `needs:contract-review` is the PM seat's to place and the at-tier review is the PM seat's to run; this PR removes no label and flips no state. Left as a draft. --- _Generated by [Claude Code](https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent f2044ef commit 7607076

3 files changed

Lines changed: 69 additions & 0 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
"@objectstack/spec": minor
3+
---
4+
5+
`CLOUD_PROVIDED_OBJECT_NAMES` (`@objectstack/spec/system`) gains a member:
6+
`sys_environment_credential`. `isPlatformProvidedObjectName('sys_environment_credential')`
7+
now returns `true`, so a reference to that name resolves instead of being
8+
diagnosed as a platform-prefixed name nothing registers (#18309).
9+
10+
This widens an accept set. The list is a closed set and the name was not in it,
11+
so the object-reference ladder now accepts a value it used to warn on, and the
12+
widening reaches every surface that consults the predicate: a dataset `object`,
13+
an action parameter `reference`, a field `reference`, a dashboard
14+
`optionsFrom.object`, a navigation `requiresObject` and a translation
15+
`objects.<name>` subtree naming `sys_environment_credential` all stop being
16+
diagnosed.
17+
18+
Why this name: as read in the cloud repository at `cb8ee7ff60`,
19+
`@objectstack/service-tenant` registers it on exactly the path the list's
20+
existing `sys_package`, `sys_package_version` and `sys_package_installation`
21+
members take — `objects/sys-environment-credential.object.ts` exported through
22+
`objects/index.ts`, listed in `tenantObjects`, spread into
23+
`manifestService.register({ objects })` by `tenant-plugin.ts`. That reading is
24+
the cloud repository's and is carried here on its filer's name; per this list's
25+
header it cannot be conformance-tested from this repo, and this change does not
26+
claim to have re-taken it.
27+
28+
Unlike the earlier additions, this one fixes no diagnostic that fires today: no
29+
`*.object.ts` in this repository references the name, so nothing shipped was
30+
being mis-diagnosed. What was wrong is the registry's own claim about the name.
31+
This repository's governed records already treat the object as real — ADR-0007's
32+
inventory table lists it as existing, and ADR-0131 cites a measured cross-tenant
33+
read of its rows — while the list that decides whether a reference resolves said
34+
no package registers it. The first author to write the reference would have been
35+
told it looked like a typo.
36+
37+
One entry is added; no other member moves and nothing is removed or narrowed.
38+
The cloud-side half of the contract — that `@objectstack/service-tenant`
39+
registers the table — is owned by the cloud repository per the list's header and
40+
is not asserted from here.

packages/spec/src/system/constants/platform-object-names.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,32 @@ describe('platform-object predicates', () => {
184184
expect(CLOUD_PROVIDED_OBJECT_NAMES, name).toContain(name);
185185
}
186186
});
187+
188+
it('resolves the tenant credential store the cloud runtime registers', () => {
189+
// The cloud-side registration is a READING TAKEN IN THE CLOUD REPOSITORY,
190+
// at `cb8ee7ff60`, and carried here on its filer's name — like every other
191+
// member of this list, it is not re-checkable from this repo, which is what
192+
// the list's own header means by "they cannot be conformance-tested from
193+
// this repo". As read there, `@objectstack/service-tenant` registers the
194+
// name on the same path as the `sys_package*` family above: declared in
195+
// `objects/sys-environment-credential.object.ts`, exported through
196+
// `objects/index.ts`, listed in `tenantObjects` in `manifest.ts`, and spread
197+
// into `manifestService.register({ objects })` by `tenant-plugin.ts`.
198+
//
199+
// Unlike `sys_license` and `sys_package_version`, no `*.object.ts` in THIS
200+
// repository references it today, so nothing here was being mis-diagnosed
201+
// while it was absent. What was wrong is the registry's own claim: this
202+
// repo's governed records already treat the object as real — ADR-0007's
203+
// inventory table lists it as `✅ exists`, and ADR-0131 §1.1 cites a
204+
// measured cross-tenant read of its rows — while the list that decides
205+
// whether a reference to it resolves said no package registers that name.
206+
// So the first author to write the reference would have been told it looked
207+
// like a typo. Pinned by name, beside `sys_license` and the package family,
208+
// for the same reason: dropping it fails one readable assertion instead of
209+
// nothing. What this test asserts is the objectstack half alone — that the
210+
// list carries the name and the predicate resolves it. The cloud half is
211+
// owned by the cloud repository and is not asserted here.
212+
expect(isPlatformProvidedObjectName('sys_environment_credential')).toBe(true);
213+
expect(CLOUD_PROVIDED_OBJECT_NAMES).toContain('sys_environment_credential');
214+
});
187215
});

packages/spec/src/system/constants/platform-object-names.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ export const PLATFORM_OBJECTS_BY_PACKAGE: Readonly<Record<string, readonly strin
149149
export const CLOUD_PROVIDED_OBJECT_NAMES: readonly string[] = [
150150
'sys_app',
151151
'sys_environment',
152+
'sys_environment_credential',
152153
'sys_environment_member',
153154
'sys_license',
154155
'sys_package',

0 commit comments

Comments
 (0)