LearnNewsExamplesServices
Frontmatter
id13153
titleEnforce no-secret metadata for dock saved layouts
stateClosed
labels
enhancementaiarchitecture
assigneesneo-gpt
createdAtJun 14, 2026, 1:34 AM
updatedAtJun 14, 2026, 3:22 AM
githubUrlhttps://github.com/neomjs/neo/issues/13153
authorneo-gpt
commentsCount1
parentIssue13030
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[x] 13147 Persist harness dock layouts with fail-closed restore
blocking[]
closedAtJun 14, 2026, 3:22 AM

Enforce no-secret metadata for dock saved layouts

Closed v13.1.0/archive-v13-1-0-chunk-2 enhancementaiarchitecture
neo-gpt
neo-gpt commented on Jun 14, 2026, 1:34 AM

Context

Follow-up from the cross-family review of PR #13152. The PR shipped saved-layout helpers for Neo.dashboard.DockZoneModel and was approved as merge-eligible; the review surfaced one non-blocking security-contract watch item: the helper rejects known runtime/credential keys via a denylist and rejects non-JSON values, but free-form metadata can still persist a JSON string under a non-denylisted sensitive key such as apiKey, sessionKey, or authKey.

Release classification: post-release (Approve-as-is follow-up — non-blocking; #13152 remains merge-eligible without this).

Live latest-open sweep: checked latest 20 open issues immediately before creation; no equivalent dock saved-layout metadata-secret ticket found. A2A in-flight claim sweep: checked latest 30 messages; no overlapping [lane-claim] / [lane-intent] found. Local exact sweep: rg "dock layout|dock-layout|saved layout|saved-layout|dockLayout|metadata secret|apiKey|sessionKey|authKey|HarnessDockZoneModel|createSavedLayout|restoreSavedLayout" resources/content/issues resources/content/discussions; no equivalent ticket found. KB semantic sweep: ask_knowledge_base("dock layout saved layout metadata secrets createSavedLayout restoreSavedLayout HarnessDockZoneModel") confirmed HarnessDockZoneModel.md already documents that layout metadata must not contain secrets.

The Problem

The documented contract is stricter than the current mechanical guard. learn/agentos/HarnessDockZoneModel.md already states that saved-layout metadata is JSON-only descriptive data and must not contain credentials, PATs, access tokens, or harness bridge tokens. PR #13152 enforces part of that boundary by rejecting non-JSON values and known forbidden key names, but the free-form metadata object remains denylist-governed.

That means a value like {metadata: {apiKey: "sk-live-x"}} is JSON-serializable and can round-trip unless the key appears in the exact forbidden-key set. The issue is not that #13152 is unsafe to merge; metadata is operator-authored annotation, and the PR already blocks the obvious runtime/preview credential keys. The issue is that the persistence helper now represents a durable contract, and future storage/UI consumers will treat its output as safe unless the contract is enforced mechanically or narrowed explicitly.

The Architectural Reality

Neo.dashboard.DockZoneModel owns the pure saved-layout projection:

  • DockZoneModel.LAYOUT_SCHEMA defines neo.harness.dockLayout.v1.
  • createSavedLayout(document, metadata) wraps a validated dock-zone document into a saved-layout object.
  • restoreSavedLayout(savedLayout) fail-closes on malformed wrappers before returning a dock-zone document.
  • learn/agentos/HarnessDockZoneModel.md is the durable contract doc for dockZone.v1, dockPreview.v1, and dockLayout.v1.

The current contract doc already covers the no-secret metadata rule, so this ticket should not add a redundant doc-only restatement. The work belongs in the helper/test layer unless implementation discovers the doc wording needs a narrow sync.

The Fix

Choose one narrow contract shape and enforce it in src/dashboard/DockZoneModel.mjs with focused tests in test/playwright/unit/dashboard/DockZoneModel.spec.mjs:

  1. Prefer an allowlist for layout-wrapper metadata keys if the storage/UI leaf has a known small surface; or
  2. Extend the forbidden-key detection to cover common credential-key aliases such as apiKey, sessionKey, authKey, and compound forms like apiToken, while preserving the current recursive JSON-only guard; or
  3. Explicitly narrow metadata to documented non-secret operator annotations and fail closed on suspicious key names.

The implementation should keep the helper pure and storage-backend-free. It should not introduce a persistence service or UI in this ticket.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
DockZoneModel.createSavedLayout(document, metadata) metadata handling learn/agentos/HarnessDockZoneModel.md saved-layout metadata contract; PR #13152 review finding Reject metadata that appears to carry credentials/secrets before producing a saved-layout wrapper Return {layout: null, errors: [...]} without mutating caller input; preserve existing non-secret metadata behavior Existing HarnessDockZoneModel.md contract already states no-secret metadata; update only if exact behavior narrows the documented contract Focused unit tests for suspicious metadata keys and allowed metadata
DockZoneModel.restoreSavedLayout(savedLayout) metadata handling Same saved-layout contract Fail closed if a saved layout wrapper already contains suspicious secret metadata keys Return {document: null, errors: [...]}; never normalize/restore the unsafe layout Same as above Focused restore-side unit test

Decision Record impact

none — this tightens the implementation to match the existing dock-zone contract; no ADR change.

Acceptance Criteria

  • createSavedLayout() rejects a wrapper-level metadata object containing secret-like keys not covered by the current exact denylist, including at least apiKey, sessionKey, and authKey or a justified alternative key policy.
  • restoreSavedLayout() rejects a saved-layout wrapper containing the same secret-like metadata keys.
  • Non-secret JSON metadata still round-trips, and caller input remains unmutated.
  • Existing forbidden runtime/preview/credential-field tests remain green.
  • Focused Playwright unit coverage passes under the custom unit config.

Out of Scope

  • Adding a storage backend for saved layouts.
  • Building the dock layout UI.
  • Reworking the dock-zone model schema beyond metadata-secret enforcement.
  • Duplicating the saved-layout contract doc unless the chosen key policy materially narrows the documented contract.

Avoided Traps

  • Treating this as a blocker for PR #13152: the review verdict was approval; this is a follow-up, not a hidden Required Action.
  • Adding another doc-only warning while the code still accepts the unsafe metadata shape.
  • Persisting a broader runtime/session/window object to solve a metadata problem.

Related

Related: #13152 Related: #13147 Related: #13030 Related: #13012

Origin Session ID: 0ed5b1b0-739e-40e5-93e6-21a2e567ec24

Handoff Retrieval Hint: "dock saved layout metadata apiKey secret createSavedLayout restoreSavedLayout"; review anchor PR #13152 Ada approval PRR_kwDODSospM8AAAABC8D5zQ.