# Bank Composition Persistence and Snapshot Propagation Decision

Status: Decided
Cycle: 2026-03
Domain Owner: `docs/studio`
Cross-Domain Impact: `docs/packer`

## Context

`Bank Composition` reaches across Studio and packer when the developer clicks `apply`.

That write path must:

- persist selected ordered files into `asset.json`;
- use the newer `artifacts` representation instead of the older `inputsByRole` shape;
- refresh enough runtime state for `Asset Details` to become consistent again after apply.

The earlier `Bank Composition` decisions already fixed:

- DTO projection:
  [`Bank Composition Details DTO Projection Decision.md`](./Bank%20Composition%20Details%20DTO%20Projection%20Decision.md)
- base components:
  [`Bank Composition Base Components Decision.md`](./Bank%20Composition%20Base%20Components%20Decision.md)
- section shell:
  [`Bank Composition Section Shell Decision.md`](./Bank%20Composition%20Section%20Shell%20Decision.md)
- middleware and staged editing:
  [`Bank Composition Middleware and Staged Editing Decision.md`](./Bank%20Composition%20Middleware%20and%20Staged%20Editing%20Decision.md)
- workspace bus interaction:
  [`Bank Composition WorkspaceBus Interaction Decision.md`](./Bank%20Composition%20WorkspaceBus%20Interaction%20Decision.md)

This decision closes the persistence direction discussed in:

- [`Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md`](../agendas/Agenda-06-Asset-Bank-Composition-Persistence-and-Snapshot-Propagation.md)

## Decision

Route `Bank Composition` apply through packer and persist selection under `asset.json` `artifacts`.

The first-wave rules are:

1. Studio must not write `asset.json` directly;
2. the packer service owns validation, persistence, and minimal snapshot refresh for selected bank-composition files;
3. `artifacts` replaces the older `inputsByRole` representation for this flow;
4. selected file order must remain explicit in persisted data rather than relying on array position alone;
5. after a successful apply, Studio must refresh from persisted state rather than trusting stale draft state.

The minimal successful apply flow is:

1. Studio submits the selected ordered files to the packer service;
2. packer updates `asset.json` under the `artifacts` representation;
3. packer refreshes the minimal runtime snapshot state required by `Asset Details`;
4. Studio rebinds the section from that refreshed persisted state;
5. the section returns to consistent read-only mode.

The minimum refreshed state after apply must include:

- persisted `selected` rows;
- the current `available` projection used by `Asset Details`;
- recalculated capacity state;
- recalculated blockers or eligibility state relevant to the section.

The failure rules are:

1. if apply fails, the draft must not be discarded;
2. the section must remain in editing mode;
3. the middleware/controller should publish `BankCompositionApplyFailed`;
4. the UI should show a local failure surface;
5. the user must still be able to retry, reset, or cancel.

## Justification

This keeps write ownership in the correct domain boundary.

Packer already owns asset mutation and runtime refresh logic.
Letting Studio write manifests directly would duplicate rules and create drift between UI and runtime behavior.

The Studio should only submit the apply request and react to the result.
The packer service is the owner of validation, persistence, and state propagation.

Refreshing from persisted state after success is also necessary.
Otherwise the section would keep trusting stale draft state and could diverge from what packer actually accepted and wrote.

Preserving the draft on failure is the correct staged-edit behavior.
The user should not lose work because persistence failed.

## Invariants and Constraints

The following constraints now apply:

1. Studio is not the manifest writer for `Bank Composition`;
2. `artifacts` is the persistence path for selected bank-composition files;
3. `inputsByRole` is not the write target for this flow;
4. successful apply requires snapshot refresh before the section settles back to read-only mode;
5. failed apply must preserve draft state and editing mode.

## Explicit Non-Decisions

This decision does not yet define:

- the exact final `asset.json` `artifacts` schema beyond explicit ordered file persistence;
- the concrete packer request/response message names;
- the exact Java event class payloads for apply success or failure;
- broader manifest migration strategy outside this `Bank Composition` flow.

## Propagation Targets

- Studio specs:
  [`4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md)
- Studio code:
  bank-composition apply flow, failure handling, and section refresh behavior
- Packer docs and code:
  `asset.json` `artifacts` persistence, write-path integration, and minimal runtime snapshot refresh after apply

## Validation Notes

Examples implied by this decision:

- after a successful apply, the section should reload from the refreshed persisted state instead of keeping the old draft instance;
- if packer rejects an apply, the selected rows remain in the draft so the user can adjust and retry;
- selected bank-composition files must be written through `artifacts`, not through `inputsByRole`.
