Skip to content

refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) - #3950

Merged
os-zhuang merged 3 commits into
mainfrom
claude/sharing-rules-schema-bypass-h4c7xr
Jul 29, 2026
Merged

refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up)#3950
os-zhuang merged 3 commits into
mainfrom
claude/sharing-rules-schema-bypass-h4c7xr

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Follow-up to #3945 (merged). Found while building the empty-state gate: allowedSources documented [] as admitting every source, and checking who enforced that turned up nobody.

A security control set that was never wired to anything

DynamicLoadingConfigSchema, PluginDiscoveryConfigSchema and PluginDiscoverySourceSchema declared:

Key What it promises
defaultSandbox sandbox dynamically loaded plugins
requireIntegrity require integrity-hash verification for remote sources
allowedSources restrict which plugin source types may load
discovery.requireApproval require admin approval before loading a discovered plugin

None of it was ever wired to anything. The three schemas were an island — not composed into any parent schema, not read by any runtime, referenced only by their own round-trip tests. They were nonetheless published into json-schema/ and the authorable key surface, where an author (very often an AI, ADR-0033) reads them as capabilities this platform has.

Someone reading the spec could reasonably conclude ObjectStack sandboxes dynamically loaded plugins. It does not.

That is the ADR-0049 false-compliance shape, and the precedent for a SAFETY-shaped instance is to remove rather than mark dead: tool.requiresConfirmation was pruned in #3715 because it was "unenforced on every path, so it was false compliance, not merely dead". Same case, one layer up.

No tombstones, deliberately — and how the guard was cleared

build-schemas.ts guards removals in two stages, and both fired:

  1. Schema-level — three published schemas disappeared. The guard's own prescribed remedy for a deliberate removal is to drop the keys from json-schema.manifest.json in the same PR. Done.
  2. Key-level — 15 authorable keys disappeared. The prescribed remedy is retiredKey() tombstones + a D2 conversion + a major changeset.

Stage 2's remedy is not applicable here, and the exemption is the interesting part of this PR. A tombstone earns its keep by making a removal audible at a parse the author actually reaches — and nothing parses these schemas. The prescription could never be delivered. Meanwhile the silent-strip the guard exists to prevent was already these keys' permanent condition: writing one has always been a no-op, because no parent schema ever accepted them. Removing them does not create that failure mode; it removes the documentation of a thing that never worked.

So the baseline entries in json-schema.manifest.json and authorable-surface.json are dropped here as the deliberate removal both files document as legitimate, rather than tombstoning 15 keys nobody could have successfully authored. The file itself carries a block comment recording this reasoning where the schemas used to be, so the next reader does not have to reconstruct it.

Breaking, in the narrow sense

packages/spec/src/kernel/index.ts re-exports the module with export *, and ./kernel is a published subpath — so DynamicLoadingConfig, PluginDiscoveryConfig, PluginDiscoverySource and their schemas were importable as types. Nothing in this repo imported them. Marked major because removing a public export is breaking regardless of use; in practice it folds into the unreleased 17.0.0.

Scope — what is deliberately left alone

ActivationEventSchema stays: it is the one export in this file with real consumers (7).

The remainder — DynamicLoadRequest, DynamicUnloadRequest, DynamicPluginResult, PluginSource, DynamicPluginOperationalso has no runtime consumer today, so the whole file except ActivationEventSchema is dead surface. It is left in place because those are operation contracts, not security promises: the enforce-or-remove call on them is a design decision, not a correction, and the requiresConfirmation precedent draws its line at exactly that distinction.

Rebuilding this surface is a design job, not a schema job: write the runtime first, then declare only what it enforces.

Verification

  • packages/spec: 263 files, 6856 tests, all passing (−2: the removed schemas' round-trip tests). tsc --noEmit clean.
  • All six spec gates green: check:docs, check:liveness, check:empty-state, check:spec-changes, check:upgrade-guide, check:skill-docs.
  • check:authorable-surface passes with the baselines updated — 1784 → 1782 schemas, 8599 → 8584 keys.
  • The allowedSources entry added to the empty-state registry in chore(spec): classify what a restriction-shaped property's EMPTY value means (#3896 follow-up) #3945 is removed with its schema, and that gate re-verified green (19 statements, all classified).
  • Reference docs regenerated; content/docs/references/kernel/plugin-runtime.mdx loses the three sections.

Generated by Claude Code

…ig that never existed (#3896)

DynamicLoadingConfigSchema, PluginDiscoveryConfigSchema and
PluginDiscoverySourceSchema declared a plugin security control set —
defaultSandbox, requireIntegrity, allowedSources, and discovery's
requireApproval ("require admin approval before loading discovered plugins").

None of it was ever wired to anything. The three schemas were an island: not
composed into any parent schema, not read by any runtime, referenced only by
their own round-trip tests. They were nonetheless published into json-schema/
and the authorable key surface, where an author — very often an AI (ADR-0033) —
reads them as capabilities this platform has. Someone reading the spec could
reasonably conclude ObjectStack sandboxes dynamically loaded plugins. It does
not.

That is the ADR-0049 false-compliance shape, and the precedent for a
SAFETY-shaped instance is to remove rather than mark dead:
tool.requiresConfirmation was pruned in #3715 because it was "unenforced on
every path, so it was false compliance, not merely dead". Same case, one layer
up. Found while building the empty-state gate (#3945): allowedSources documented
[] as admitting every source, and checking who enforced that turned up nobody.

No retiredKey() tombstones, deliberately. A tombstone earns its keep by making a
removal audible at a parse the author actually reaches — and nothing parses
these schemas, so the prescription could never be delivered. The silent-strip
the key-vanish guard exists to prevent was already these keys' permanent
condition: writing one has always been a no-op, because no parent schema ever
accepted them. The baseline entries in json-schema.manifest.json and
authorable-surface.json are dropped here as the deliberate removal both files
document as the legitimate path, rather than tombstoning 15 keys nobody could
have successfully authored.

Breaking in the narrow sense: kernel/index.ts re-exports this module with
`export *` and ./kernel is a published subpath, so the types were importable.
Nothing in this repo imported them; it folds into the unreleased 17.0.0.

The rest of the file is untouched, including ActivationEventSchema — the one
export in it with real consumers. The remainder (DynamicLoadRequest,
DynamicUnloadRequest, DynamicPluginResult, PluginSource,
DynamicPluginOperation) also has no runtime consumer, but those are operation
contracts rather than security promises, so the enforce-or-remove call on them
is a design decision, not a correction.

spec: 263 files / 6856 tests green, tsc clean, all six generated-artifact and
liveness gates pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QuViRSR1j6GJjf9qGbnqFX
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 29, 2026 12:44pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

105 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/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.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/your-first-project.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/sms-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 @objectstack/spec)
  • 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/rls.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/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/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 @objectstack/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/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.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/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.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.

claude added 2 commits July 29, 2026 12:35
…in-loading exports

The third guard on a deliberate removal, after json-schema.manifest.json and
authorable-surface.json: check:api-surface diffs the public export list and
correctly reported 7 exports gone from ./kernel. Same exemption rationale as
the other two baselines — the removal is the point of the PR, and the major
changeset is already in place.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QuViRSR1j6GJjf9qGbnqFX
…napshot came from stale dist

build-api-surface.ts reads the built dist (its header says to run it after a
build). The previous regeneration ran against a dist compiled before this
branch's removal — so the snapshot KEPT the 7 removed plugin-loading exports
and DELETED six exports that had landed on main since (UpdateManyRecord*,
ReportSort*, reportSelectionOrder). CI read that as 7 breaking + 6 added.

Rebuilt, regenerated: the diff is now exactly the intended shape — the seven
plugin-loading exports gone, the six main-side exports restored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QuViRSR1j6GJjf9qGbnqFX
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants