Skip to content

fix(security,release): qualified FLS keys + lint, PROTOCOL_VERSION auto-sync, D11 honest marking#2800

Merged
os-zhuang merged 2 commits into
mainfrom
feat/release-sync-fls-d11
Jul 10, 2026
Merged

fix(security,release): qualified FLS keys + lint, PROTOCOL_VERSION auto-sync, D11 honest marking#2800
os-zhuang merged 2 commits into
mainfrom
feat/release-sync-fls-d11

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Three hardening items from the permission-zoo audit round.

FLS: bare keys were a silent runtime no-op — now impossible to author

The evaluator matches field-permission keys by <object>.<field> prefix (getFieldPermissions: key.startsWith(objectName + '.')), so a bare budget key matches nothing — the showcase contributor's declared budget masking never enforced, and the earlier verification's "budget PATCH → 400" was actually the spent_within_budget validation rule rejecting a tiny budget, not FLS (misattribution now corrected on the record). Fixes at every layer:

  • Showcase: keys qualified (showcase_project.budget / .spent / .budget_remaining) with a comment explaining why.
  • Lint: new D7 rule security-fls-unqualified-key (error + fix-it) — a bare FLS key is exactly the plausible-but-wrong shape AI authoring produces, and it fails silently; now it fails the build with the qualified-key prescription. 2 new fixtures.
  • Dogfood: the permission-zoo test now proves the served pipeline denies a contributor's budget write (with a LARGE value so the validation rule can't be the rejector) while an ordinary field edit passes, and the value is unchanged after the denial. 13/13 green.

Release: PROTOCOL_VERSION can no longer drift

changeset version now chains scripts/sync-protocol-version.mjs (regenerates the handshake constant from the spec package major; idempotent, fails loudly on unparseable state). Root cause of the 14.0.0 main breakage (#2769): release PRs opened by changesets/action with the default GITHUB_TOKEN never trigger CI (GitHub's anti-recursion rule) — the lockstep test existed but could only fire after the merge. Fixing the value at version time is the one spot that cannot be skipped. Verified both branches: in-lockstep no-op and 13→14 repair.

D11: externalSharingModel honestly marked (enforce-or-mark)

The dial has no runtime consumer (authoring lint security-external-wider-than-internal + Studio Ext badges only; effectiveSharingModel reads sharingModel alone, and no principal ever evaluates as external today). Its liveness entry moves from the bespoke authorable status (outside the documented vocabulary, no gate ever checked it) to planned + authorWarn, so authors are told the dial does not evaluate yet; the sharing docs, design doc, and showcase comments now say the evaluator branch lands with the principal-taxonomy phase (#2696).

Also noted: ADR-0091 (grant lifecycle) was already authored and accepted upstream — no duplicate work.

Verification

128/128 turbo tasks green (incl. dogfood with the new FLS enforcement assertion and the lint suite at 34 tests).

🤖 Generated with Claude Code

…to-sync, D11 honest marking

FLS (permission-zoo audit): the runtime evaluator matches field-permission
keys by <object>.<field> prefix — a bare `budget` key matches NOTHING, so
the showcase contributor's declared budget masking was a silent runtime
no-op (the earlier "FLS proof" was actually the spent_within_budget
validation rule rejecting a tiny budget). Fixed at every layer: the zoo
keys are qualified (showcase_project.budget …); a new D7 lint rule
`security-fls-unqualified-key` (error + fix-it) rejects bare keys at
compile time — the exact plausible-but-wrong shape AI authoring produces;
and the permission-zoo dogfood now proves the served pipeline denies a
contributor's budget write while allowing ordinary field edits.

Release: `changeset version` now chains scripts/sync-protocol-version.mjs,
regenerating the PROTOCOL_VERSION handshake constant from the spec package
major. Release PRs opened by changesets/action with the default
GITHUB_TOKEN never trigger CI (GitHub anti-recursion), so the lockstep
guard could only fire AFTER a release merged — fixing the value at version
time closes the drift class that broke main at 14.0.0 (#2769).

D11: `externalSharingModel` has no runtime consumer yet (authoring lint +
Studio badges only). Its liveness entry moves from the bespoke `authorable`
status to the documented `planned` + authorWarn (enforce-or-mark), and the
sharing docs, design doc, and showcase comments now state explicitly that
external-principal evaluation lands with the principal-taxonomy phase
(#2696).

ADR-0091 (grant lifecycle) was already authored and accepted upstream — no
duplicate draft.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 10, 2026 3:39pm

Request Review

…ed-key + ADR-0091 L1 rules)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling size/m and removed documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling labels Jul 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/dogfood, @objectstack/lint, @objectstack/spec.

94 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via packages/dogfood, @objectstack/lint, @objectstack/spec)
  • content/docs/permissions/delegated-administration.mdx (via packages/dogfood)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 7449476 into main Jul 10, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the feat/release-sync-fls-d11 branch July 10, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant