test(runtime): pin standalone-stack's app-default resolution against the real helper, not a copy of it - #7252
Merged
Conversation
…the REAL helper `standalone-stack.test.ts` hand-copied `appDefaultPermissionSetName` and titled the copy "the exact CLI wiring" — a conformance claim over a duplicate of the rule, green through any change to the real helper. The mirror's stated reason had already expired: `@objectstack/plugin-security` is a plain `dependencies` entry of `@objectstack/runtime`, and another test in the same package already imports from it. Import the real `appSecurityPluginOptions` / `appDefaultPermissionSetName` instead, anchored on `appSecurityPluginOptions` because that is what `serve.ts` calls today (#7001). Also make the fixture discriminate: the non-default set now sits FIRST in the artifact, and the surfaced order is asserted unsorted — the precondition the first-`isDefault` rule depends on, and this package's half of it. Fixes #7092 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0158ZQo7LiHSxGWpYKuPq1wu
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
This was referenced Aug 10, 2026
os-help
marked this pull request as ready for review
August 10, 2026 04:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7092
packages/runtime/src/standalone-stack.test.tshand-copied the body ofappDefaultPermissionSetNameand asserted against the copy in a case titled"the surfaced config drives appDefaultPermissionSetName → the app profile
(the exact CLI wiring)". A conformance claim over a duplicate of the rule:
green through any change to the real helper, while
objectstack dev/servedid something else.
The mirror's stated reason had already expired
The comment justified the copy as:
Measured on the merge base, that is false:
packages/runtime/package.jsoncarries"@objectstack/plugin-security": "workspace:*"in
dependencies— notdevDependencies, a plain runtime edge.packages/runtime/src/domains/share-links-enforcement-context.test.ts:55imports
PermissionDeniedError, SecurityPlugin.@objectstack/plugin-securitydepends only oncore,formula,platform-objects,spec.So the card's option 1 needed no
package.jsonchange at all — the edge itproposed adding is already there. Zero dependency edges added by this PR.
What this PR does
Deletes the mirror and imports the real helpers. The anchor is
appSecurityPluginOptionsrather than the bare name helper, because that iswhat
serve.tscalls today (#7001):new SecurityPlugin(appSecurityPluginOptions(config))— which closes the"one level below what serve.ts actually calls" staleness the card notes.
The fixture now discriminates: the non-default
app_contributorset sitsfirst in the artifact's
permissions[], so the resolution cases disagreewith "take
permissions[0]" instead of accidentally agreeing with it. And thesurfaced-order assertion is no longer
.sort()ed — declaration order is theprecondition the first-
isDefaultrule depends on, and surfacing it faithfullyis this package's half of that rule. That invariant was previously unpinned.
Why the assertion stays in
packages/runtime(not moved topackages/cli)The card recommended option 2. Measured, the CLI side of the claim is already
pinned and moving would duplicate cost without adding a claim:
packages/cli/src/commands/serve-verify-security-parity.contract.test.tsalready pins that
serve.tsconstructsSecurityPluginexactly once viaappSecurityPluginOptions(config), and that it agrees withbootStack.packages/plugins/plugin-security/src/app-default-permission-set.test.tsalready pins the rule's substance against the real helper: first-
isDefaultwins, the
undefinedvs{ fallbackPermissionSet: undefined }distinction,top-level-only reads, and that the option lands on the plugin's baseline
service.
What neither can see — and what this file uniquely owns — is the
composition: that the config
createStandaloneStack/createDefaultHostConfigactually return is a config that resolution reads correctly. Moving it to
packages/cliwould mean either re-running the 60s standalone boot there, orhand-building a config — i.e. replacing a mirror of the rule with a mirror of
the surfacing. Cross-references to all three homes are now in the file's header.
Reverse verification (predicted direction: red — and it is)
Ablated the real helper in
plugin-security(dropped theps.isDefault === truediscrimination), rebuilt its dist, and ran the case:Then, with the same ablation still in place, restored the pre-fix test file
from
origin/mainand ran itsexact CLI wiringcase:That is the defect, measured rather than argued: the old case is green over
a real helper whose resolution has been deleted; the new case is red. Both
files and the helper were restored afterwards (via
git checkout, nevergit stash), and the suite re-run green.Verification
pnpm --filter '@objectstack/runtime^...' build— build closure first, green.@objectstack/runtimefull suite: 118 test files, 1837 tests passed.pnpm --filter @objectstack/runtime typecheck— clean.pnpm check:type-check-debt(--self-test && --re-measure, afterturbo run build): OK, 33 entries re-measured, "none above its recordednumber".
@objectstack/runtimemeasures 225 against a recorded ceiling of227 — unchanged by this PR: reproducing the gate's own sibling-tsconfig
measurement on the branch and on
origin/main's version of the file gave225 both ways, with 0 errors attributable to
src/standalone-stack.test.tsin either. The ledger is not raised.node scripts/check-nul-bytes.mjs— OK; plus a wider self-scan(
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]') over the touched file, no hits.npx eslint packages/runtime/src/standalone-stack.test.ts— clean.Scope
One file changed:
packages/runtime/src/standalone-stack.test.ts. Nopackage.jsonedit, no production code, no changeset — tests-only, nothinguser-visible ships. Needs
skip-changeset.Generated by Claude Code