Part of #14122 · related #14512 (the emitter half) and #15004 (the acceptance pin).
Filed from the by-shape sweep card #15007 requires before implementing — the sweep the card asks for precisely because the two earlier enumerations scoped themselves by package name up front and each missed a package. This one turns up two more packages, neither of which the program scopes: @objectstack/verify and @objectstack/plugin-dev.
Not folded into #15007 per that card's instruction ("If another package turns up, file it as 5/4 rather than folding it in").
The sites
| Package |
file:line |
Reads |
What an option-B artifact does to it |
@objectstack/verify |
packages/verify/src/derive.ts:176 |
config.objects |
deriveCrudCases derives ZERO CRUD round-trip cases |
@objectstack/verify |
packages/verify/src/derive.ts:180 |
config.datasources |
the datasource-by-name map is empty, so every derived case loses its datasource |
@objectstack/verify |
packages/verify/src/rls.ts:134 |
config.positions |
declaredPositionNames returns [] — no persona is built for any declared position |
@objectstack/verify |
packages/verify/src/rls.ts:346 |
config.objects |
rlsProbePermissionSet builds an EMPTY probe permission set — the persona that makes an RLS run a probe grants nothing and narrows nothing |
@objectstack/plugin-dev |
packages/plugins/plugin-dev/src/dev-plugin.ts:526 |
options.stack.translations |
the I18nServicePlugin auto-detect never fires, so a multi-package app boots os dev with the in-memory i18n fallback instead of the file-based service |
Reached with a composed multi-package config today:
packages/cli/src/commands/verify.ts:155 calls declaredPositionNames(config) on the loaded config; rlsProbeSecurity / deriveCrudCases run off the same object.
new DevPlugin({ stack: config }) is the documented construction (packages/plugins/plugin-dev/src/index.ts:36).
Why this is worse than a missing collection, not merely equal to one
The other reader cards lose a capability. @objectstack/verify loses the verification itself, and reports success while doing it: zero derived cases and an empty RLS probe set are a green run that measured nothing. A multi-package app under option B would get a passing os verify that asserts nothing about any of its objects — the failure mode #15004 exists to make loud, arriving in the one place where a false green is most expensive.
Acceptance (suggested — the ruling's shape, not re-adjudicated here)
May well want splitting into 5/4 and 6/4 — one card per package, per the ruling's "each site separately reviewable and revertible". Filed as one so the finding is not lost; the split is the PM's call.
The sweep this came from, stated so the next one can be compared against it
By SHAPE, across all of packages/, never against a package list. The collection key set was derived, not transcribed: ObjectStackDefinitionSchema shape keys intersected with AssembledPackageBodySchema shape keys = the 37 package-owned collections (actions agents analyticsCubes apis apps books capabilities connectors dashboards data datasets datasourceMapping datasources devPlugins docs emailTemplates flows functions hooks jobs mappings objectExtensions objects pages permissions plugins positions reports requires sharingRules skills tiers tools translations viewItems views webhooks), complement = the 7 envelope keys.
Four shapes searched over every packages/** source file (tests, fixtures and dist/ excluded):
- property access on a stack-ish identifier —
(config|cfg|bundle|artifact|stack|stackConfig|appConfig|projectConfig|loadedConfig|resolvedConfig|definition|objectstackConfig|osConfig|conf)?.KEY
- destructuring —
const { KEY, ... } = ...(config|bundle|stack|artifact)
- bracket access —
identifier['KEY']
this./options. member reads — (this|options).(stack|bundle|artifact|config)?.KEY
Plus two structural passes: every parameter typed ObjectStackDefinition / ObjectStackConfig / StackDefinition / AssembledPackageBody, and every site that opens the artifact itself (objectstack.json + readFileSync / JSON.parse).
Triaged as NOT findings, so the next sweep does not re-litigate them:
@objectstack/plugin-auth — this.config.plugins is AuthPluginConfig.plugins (better-auth plugin options), not the stack's plugins collection.
@objectstack/objectql engine.ts:13946-13965 — config.datasources / config.objects / config.hooks on the ENGINE config, a name-keyed record, not the stack's arrays.
@objectstack/service-analytics analytics-service.ts:734 — config.datasets on AnalyticsServiceConfig (the same object carrying getObjectFieldNames), not a stack.
@objectstack/metadata-protocol build-probes.ts:171 — config there is a VIEW body's config field.
@objectstack/metadata-core form-predicate-root-policy.ts:445 — definition.views on an authoring-time definition, reached from lint rather than from a boot.
@objectstack/lint (201 hits) and packages/spec (95) — the linter's authoring-time surface and the schemas themselves.
plugin-email / plugin-webhooks / plugin-security bootstrap-declared-* — the stack.KEY spellings there are in PROSE; those readers take their items from the metadata service.
loadArtifactBundle has callers in packages/runtime only.
- The i18n-extract configs under
packages/*/scripts/ are single-package authoring stacks with no packages[].
Generated by Claude Code
Part of #14122 · related #14512 (the emitter half) and #15004 (the acceptance pin).
Filed from the by-shape sweep card #15007 requires before implementing — the sweep the card asks for precisely because the two earlier enumerations scoped themselves by package name up front and each missed a package. This one turns up two more packages, neither of which the program scopes:
@objectstack/verifyand@objectstack/plugin-dev.Not folded into #15007 per that card's instruction ("If another package turns up, file it as 5/4 rather than folding it in").
The sites
file:line@objectstack/verifypackages/verify/src/derive.ts:176config.objectsderiveCrudCasesderives ZERO CRUD round-trip cases@objectstack/verifypackages/verify/src/derive.ts:180config.datasources@objectstack/verifypackages/verify/src/rls.ts:134config.positionsdeclaredPositionNamesreturns[]— no persona is built for any declared position@objectstack/verifypackages/verify/src/rls.ts:346config.objectsrlsProbePermissionSetbuilds an EMPTY probe permission set — the persona that makes an RLS run a probe grants nothing and narrows nothing@objectstack/plugin-devpackages/plugins/plugin-dev/src/dev-plugin.ts:526options.stack.translationsI18nServicePluginauto-detect never fires, so a multi-package app bootsos devwith the in-memory i18n fallback instead of the file-based serviceReached with a composed multi-package config today:
packages/cli/src/commands/verify.ts:155callsdeclaredPositionNames(config)on the loaded config;rlsProbeSecurity/deriveCrudCasesrun off the same object.new DevPlugin({ stack: config })is the documented construction (packages/plugins/plugin-dev/src/index.ts:36).Why this is worse than a missing collection, not merely equal to one
The other reader cards lose a capability.
@objectstack/verifyloses the verification itself, and reports success while doing it: zero derived cases and an empty RLS probe set are a green run that measured nothing. A multi-package app under option B would get a passingos verifythat asserts nothing about any of its objects — the failure mode #15004 exists to make loud, arriving in the one place where a false green is most expensive.Acceptance (suggested — the ruling's shape, not re-adjudicated here)
resolveArtifactPackageOrder(@objectstack/core, ADR-0130 D4+D5, since fix(metadata): register a packages[] artifact per package at the metadata door so every object has one owner across every door (#14599) #14643), flattened top level first so today's additive artifact answers bit-identically.composeStacksandpackages/spec/src/stack.zod.tsare untouched, same as the rest of the program.May well want splitting into 5/4 and 6/4 — one card per package, per the ruling's "each site separately reviewable and revertible". Filed as one so the finding is not lost; the split is the PM's call.
The sweep this came from, stated so the next one can be compared against it
By SHAPE, across all of
packages/, never against a package list. The collection key set was derived, not transcribed:ObjectStackDefinitionSchemashape keys intersected withAssembledPackageBodySchemashape keys = the 37 package-owned collections (actions agents analyticsCubes apis apps books capabilities connectors dashboards data datasets datasourceMapping datasources devPlugins docs emailTemplates flows functions hooks jobs mappings objectExtensions objects pages permissions plugins positions reports requires sharingRules skills tiers tools translations viewItems views webhooks), complement = the 7 envelope keys.Four shapes searched over every
packages/**source file (tests, fixtures anddist/excluded):(config|cfg|bundle|artifact|stack|stackConfig|appConfig|projectConfig|loadedConfig|resolvedConfig|definition|objectstackConfig|osConfig|conf)?.KEYconst { KEY, ... } = ...(config|bundle|stack|artifact)identifier['KEY']this./options.member reads —(this|options).(stack|bundle|artifact|config)?.KEYPlus two structural passes: every parameter typed
ObjectStackDefinition/ObjectStackConfig/StackDefinition/AssembledPackageBody, and every site that opens the artifact itself (objectstack.json+readFileSync/JSON.parse).Triaged as NOT findings, so the next sweep does not re-litigate them:
@objectstack/plugin-auth—this.config.pluginsisAuthPluginConfig.plugins(better-auth plugin options), not the stack'spluginscollection.@objectstack/objectqlengine.ts:13946-13965—config.datasources/config.objects/config.hookson the ENGINE config, a name-keyed record, not the stack's arrays.@objectstack/service-analyticsanalytics-service.ts:734—config.datasetsonAnalyticsServiceConfig(the same object carryinggetObjectFieldNames), not a stack.@objectstack/metadata-protocolbuild-probes.ts:171—configthere is a VIEW body'sconfigfield.@objectstack/metadata-coreform-predicate-root-policy.ts:445—definition.viewson an authoring-time definition, reached from lint rather than from a boot.@objectstack/lint(201 hits) andpackages/spec(95) — the linter's authoring-time surface and the schemas themselves.plugin-email/plugin-webhooks/plugin-securitybootstrap-declared-*— thestack.KEYspellings there are in PROSE; those readers take their items from the metadata service.loadArtifactBundlehas callers inpackages/runtimeonly.packages/*/scripts/are single-package authoring stacks with nopackages[].Generated by Claude Code