@@ -24,24 +24,41 @@ Architecture alignment:
2424
2525WHO CAN WRITE THIS CONFIG (#15543 ) — read this before planning a deployment
2626around any key below. A ` RestServerConfig ` is the ARGUMENT a host passes when
27- it constructs the server: never a stack collection member, never a stored
28- metadata row, never a file the CLI reads. Both doors are programmatic —
29- ` createRestApiPlugin({ api }) ` (` packages/rest/src/rest-api-plugin.ts ` ) and
30- ` createHonoServerPlugin({ restConfig }) `
31- (` packages/plugins/plugin-hono-server/src/hono-plugin.ts ` ).
32-
33- No shipped boot path opens either door with a config of its own. ` os serve `
34- (` packages/cli/src/commands/serve.ts ` ) constructs the plugin with a fixed
35- argument carrying exactly two CLI-derived keys — ` api.enableProjectScoping `
36- and ` api.projectResolution ` — and the dev plugin
27+ it constructs the server: never a stack collection member and never a stored
28+ metadata row.
29+
30+ There is exactly ONE door, and it is programmatic:
31+ ` createRestApiPlugin({ api }) ` (` packages/rest/src/rest-api-plugin.ts ` ),
32+ whose ` start() ` is the only non-test site that reaches ` new RestServer(...) ` .
33+ ⚠️ ` HonoServerPlugin ` (` packages/plugins/plugin-hono-server ` ) declares a
34+ ` restConfig?: RestServerConfig ` option, but it is NOT a second door: its one
35+ reader takes ` api.basePath ` for the SPA fallback, and that plugin never
36+ constructs a REST server, so nothing below ` api.basePath ` reaches anything.
37+
38+ No shipped boot path opens that door with a config of its own. ` os serve `
39+ (` packages/cli/src/commands/serve.ts ` ) reads the stack config's own top-level
40+ ` api: ` block and forwards exactly two keys out of it —
41+ ` api.enableProjectScoping ` and ` api.projectResolution ` — into a fixed
42+ argument, through an ` as any ` cast; the dev plugin
3743(` packages/plugins/plugin-dev/src/dev-plugin.ts ` ) calls
38- ` createRestApiPlugin() ` with no config at all. So on a CLI-started deployment
39- every OTHER key here is EMBEDDER-ONLY: the whole of ` crud ` , ` metadata ` and
40- ` batch ` , and the rest of ` api ` . Its value is whatever the ` .default() ` below
41- says, and no flag, env var or config file moves it. That is the recorded
42- posture, not a gap awaiting a fix: the keys keep their runtime reads and
43- their embedder consumer, and the reachability answer ADR-0049 asks for is
44- written per key in the liveness ledger
44+ ` createRestApiPlugin() ` with no config at all. So the CLI does read a config
45+ file — it just forwards those two keys and nothing else.
46+
47+ ⇒ On a CLI-started deployment every OTHER key here is EMBEDDER-ONLY: the
48+ whole of ` crud ` , ` metadata ` and ` batch ` , and the rest of ` api ` . Its value is
49+ whatever the ` .default() ` below says, and no flag, config file or CLI option
50+ moves it.
51+
52+ ⚠️ ONE CARVE-OUT, and it is the security-relevant key: the REST server's
53+ ` normalizeConfig ` folds the environment into the effective value of
54+ ` metadata.maskObjectFields ` — ` OS_ALLOW_UNMASKED_OBJECT_METADATA ` turns the
55+ ADR-0106 D8 mask OFF for a deployment that cannot otherwise reach the key.
56+ That env var is the only thing outside an embedder's argument that changes
57+ any value here. See ` maskObjectFields ` below.
58+
59+ This is the recorded posture, not a gap awaiting a fix: the keys keep their
60+ runtime reads and their embedder consumer, and the reachability answer
61+ ADR-0049 asks for is written per key in the liveness ledger
4562(` packages/spec/liveness/crud_endpoints.json ` , ` metadata_endpoints.json ` ,
4663` batch_endpoints.json ` ).
4764
0 commit comments