Skip to content

visual-artifacts: user-installed stack wins over bundled example (VA-STACK-001)#222

Merged
garagon merged 1 commit into
mainfrom
visual-artifacts-v1-stack-lookup-precedence
May 12, 2026
Merged

visual-artifacts: user-installed stack wins over bundled example (VA-STACK-001)#222
garagon merged 1 commit into
mainfrom
visual-artifacts-v1-stack-lookup-precedence

Conversation

@garagon
Copy link
Copy Markdown
Owner

@garagon garagon commented May 11, 2026

Summary

Closes VA-STACK-001 from the Visual Artifacts v1 Security Audit (architect review, 2026-05-11). Single P2 finding: named stack lookup checked the repo-bundled example before the project's user-installed stack, so a customized compliance-release was silently shadowed by the example with the same name. The render and manifest looked authoritative but described the wrong workflow.

Fix

Swap precedence in render_stack_body:

  1. $NANOSTACK_STORE/stacks/<name>/stack.json (user-installed)
  2. examples/custom-stack-template/<name>/stack.json (bundled fallback)
  3. .nanostack/config.json only for stack default (unchanged)

A user-installed stack with the same name as a bundled example always wins. Bundled fallback still applies when no user stack exists. Malformed-named-stack and stack-not-found paths are unchanged.

Files

  • bin/render-artifact.sh: swap the lookup order in render_stack_body.
  • reference/visual-artifact-contract.md: update the stack <name> row to reflect the new order.
  • ci/e2e-visual-artifacts.sh: 2 new cells (24a, 24b) covering both directions.

Regression coverage

Cell Scenario Asserts
24a User-installed compliance-release with phase user-gate + display_name "User Compliance Override" HTML shows user phases; does NOT show bundled license-audit; manifest first source is the user-installed stack file
24b No user stack, bundled example only HTML shows bundled phases; manifest first source is the examples file

Codex review trail (1 pass, clean)

Pass 1: clean.

Test plan

  • ci/check-visual-artifact-templates.sh 38/38
  • ci/e2e-visual-artifacts.sh 330/330 (was 321; +9 from cells 24a + 24b)
  • tests/run.sh 83/83
  • Architect's reproduction (user stack overrides bundled) — manifest first source now points at $NANOSTACK_STORE/stacks/compliance-release/stack.json
  • Codex pass 1 returned clean

VA-STACK-001 from the Visual Artifacts v1 Security Audit
(architect review, 2026-05-11). Single P2 finding: named stack
lookup checked examples/custom-stack-template/<name>/stack.json
BEFORE $NANOSTACK_STORE/stacks/<name>/stack.json, so a user-
installed `compliance-release` stack was silently shadowed by
the repo-bundled example with the same name.

Impact: not RCE or exfiltration. The render and manifest looked
authoritative, but described the wrong workflow. Compliance and
release reviews could approve against a DAG that was not the
project's actual stack. The contract for visual artifacts as
trustable local evidence required this gap to close.

Fix: swap precedence in render_stack_body.
  1. $NANOSTACK_STORE/stacks/<name>/stack.json (user-installed)
  2. examples/custom-stack-template/<name>/stack.json (bundled fallback)
  3. .nanostack/config.json only for `stack default` (unchanged)

A user-installed stack with the same name as a bundled example
always wins. Bundled fallback still applies when no user stack
exists. The malformed-named-stack and stack-not-found paths are
unchanged.

reference/visual-artifact-contract.md updated to reflect the new
order. The Stack invalid / Stack not found behavior is unchanged.

Regression cells:
- 24a: user-installed `compliance-release` with phase `user-gate`
  + display_name "User Compliance Override" wins. HTML shows the
  user phases, does NOT show the bundled license-audit phase, and
  the manifest first source is the user-installed stack file.
- 24b: with no user stack, the bundled example still renders.
  Manifest first source is the examples/custom-stack-template
  file.

Test count: 321 -> 330 e2e (+9). Template lint 38/38 unchanged.
Local tests/run.sh 83/83 still green.
@garagon garagon merged commit 3d391eb into main May 12, 2026
63 checks passed
@garagon garagon deleted the visual-artifacts-v1-stack-lookup-precedence branch May 12, 2026 00:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant