Skip to content

metadata: allowRuntimeCreate:false is not enforced — PUT /meta creates job and agent items the registry declares code-only #5086

Description

@baozhoutao

Found working the #3909 G8 checklist on main @ a1a855a28 (the rc.3 train tip).

#4509 closed the door on runtime-created jobs by setting registry flags:

// packages/spec/src/kernel/metadata-plugin.zod.ts:658
{ type: 'job', label: 'Background Job',, supportsOverlay: false,
  allowOrgOverride: false, allowRuntimeCreate: false,}

and its changeset states the intent unambiguously:

  • allowRuntimeCreate: falseno "create job" in Studio or via PUT /meta.
  • allowOrgOverride: false — no per-org job fork…

PUT /meta still creates one.

PUT /api/v1/meta/job/rc3_runtime_job
    {"name":"rc3_runtime_job","label":"J",
     "schedule":{"type":"cron","expression":"0 0 * * *"},"handler":"nope"}
→ 200 {"success":true,"message":"Saved customization overlay (env-wide) — type=job, name=rc3_runtime_job"}

GET /api/v1/meta/job
→ listed, with handler "nope"

handler: "nope" names no function in any compiled bundle — precisely the record #4509 argues can never be scheduled, saved and reported as success.

Not job-specific — the gate looks unenforced generally

agent is the only other type carrying allowRuntimeCreate: false. It behaves the same:

PUT /api/v1/meta/agent/rc3_agent_probe {"name":…,"label":"A","role":"assistant","instructions":"be helpful"}
→ 200 {"success":true,"message":"Saved customization overlay (env-wide) — type=agent, …}

So both flagged types accept a runtime create. A minimal-payload PUT to object / flow / job all return 422, which is schema validation firing first — that is what makes this easy to miss: the gate never runs, and only a payload that passes the schema reveals it.

supportsOverlay: false appears equally unenforced — the success message calls the row a "customization overlay" for a type declared not to support them.

Why it matters

This is the failure mode ADR-0049 exists to prevent, one level up: the enforcement flag itself is the silently-inert declaration. A reader of the registry (or of the #4509 changeset, or of the release notes) concludes Studio and PUT /meta refuse these types. Studio presumably reads allowRuntimeCreate to decide whether to show "create", so the UI honours it while the API underneath does not — the "UI-hidden but server-open" shape ADR-0066 D4 calls out for actions.

Expected

The metadata write path consults the registry's allowRuntimeCreate (and supportsOverlay / allowOrgOverride) before persisting, and refuses with a catalogued code naming the type and why it is code-only — the same shape the retired-key refusals in this same wave produce. A regression test per flagged type would pin it, since the flags are data and new types will keep arriving.

Found during the #3909 rc.3 verification (G8).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions