|
| 1 | +--- |
| 2 | +"@objectstack/spec": major |
| 3 | +--- |
| 4 | + |
| 5 | +refactor(spec)!: remove the plugin sandboxing / integrity / approval config that never existed (#3896 follow-up) |
| 6 | + |
| 7 | +`DynamicLoadingConfigSchema`, `PluginDiscoveryConfigSchema` and |
| 8 | +`PluginDiscoverySourceSchema` declared a plugin security control set — |
| 9 | +`defaultSandbox`, `requireIntegrity`, `allowedSources`, and discovery's |
| 10 | +`requireApproval` ("require admin approval before loading discovered plugins"). |
| 11 | + |
| 12 | +**None of it was ever wired to anything.** The three schemas were an island: not |
| 13 | +composed into any parent schema, not read by any runtime, referenced only by |
| 14 | +their own round-trip tests. They were nonetheless published into `json-schema/` |
| 15 | +and the authorable key surface, where an author — very often an AI (ADR-0033) — |
| 16 | +would read them as capabilities this platform has. A reader of the spec could |
| 17 | +reasonably conclude ObjectStack sandboxes dynamically loaded plugins. It does |
| 18 | +not. |
| 19 | + |
| 20 | +That is the ADR-0049 false-compliance shape, and the precedent for a |
| 21 | +SAFETY-shaped instance is to remove rather than mark dead: |
| 22 | +`tool.requiresConfirmation` was pruned in #3715 because it was "unenforced on |
| 23 | +every path, so it was false compliance, not merely dead". This is the same case, |
| 24 | +one layer up. |
| 25 | + |
| 26 | +Found while building the empty-state gate (#3945): `allowedSources` documented |
| 27 | +`[]` as admitting every source, and checking who enforced that turned up nobody. |
| 28 | + |
| 29 | +**No `retiredKey()` tombstones, deliberately.** A tombstone earns its keep by |
| 30 | +making a removal audible at a parse the author actually reaches — and nothing |
| 31 | +parses these schemas, so the prescription could never be delivered. The |
| 32 | +silent-strip that the key-vanish guard exists to prevent was already these keys' |
| 33 | +permanent condition: writing one has always been a no-op, because no parent |
| 34 | +schema ever accepted them. The guard's baseline entries in |
| 35 | +`json-schema.manifest.json` and `authorable-surface.json` are therefore dropped |
| 36 | +in this PR as the deliberate removal both files document as the legitimate path, |
| 37 | +rather than tombstoning 15 keys nobody could have successfully authored. |
| 38 | + |
| 39 | +**Breaking, in the narrow sense.** `packages/spec/src/kernel/index.ts` |
| 40 | +re-exports this module with `export *`, and `./kernel` is a published subpath, so |
| 41 | +`DynamicLoadingConfig`, `PluginDiscoveryConfig`, `PluginDiscoverySource` and |
| 42 | +their schemas were importable as types. Nothing in this repo imported them. |
| 43 | +Marked `major` because removing a public export is breaking regardless of use; |
| 44 | +in practice it folds into the unreleased 17.0.0. |
| 45 | + |
| 46 | +The rest of `plugin-runtime.zod.ts` is untouched — including |
| 47 | +`ActivationEventSchema`, the one export in the file with real consumers. Note |
| 48 | +that the remainder (`DynamicLoadRequest`, `DynamicUnloadRequest`, |
| 49 | +`DynamicPluginResult`, `PluginSource`, `DynamicPluginOperation`) also has no |
| 50 | +runtime consumer today; it is left in place because those are operation |
| 51 | +contracts, not security promises, and the enforce-or-remove call on them is a |
| 52 | +design decision rather than a correction. |
| 53 | + |
| 54 | +**Rebuilding this surface is a design job, not a schema job**: write the runtime |
| 55 | +first, then declare only what it enforces. |
0 commit comments