69 lines
5.4 KiB
Markdown
69 lines
5.4 KiB
Markdown
# Plugin Local H2 Delivery Rehearsal Design
|
|
|
|
## Context
|
|
|
|
P2-D8e2i persisted a trustworthy `PLAN_ONLY` Run, but its six scenarios were contracts rather than executions. P2-D8e2j executes those contracts without crossing the external-target authorization boundary.
|
|
|
|
Every Attempt receives a fresh in-memory H2 database in MySQL compatibility mode. The sandbox reuses the production SQL, permission, and menu JDBC Executors and the installed trusted baseline Plugin resources. Only Attempt and Receipt evidence is written to the control database. The H2 database disappears when its keeper connection closes.
|
|
|
|
## Attempt State
|
|
|
|
`factory_plugin_delivery_rehearsal_attempt` binds an execution to the immutable parent Run through copies of the Run key, acceptance fingerprint, and scenario fingerprint. It also stores:
|
|
|
|
- monotonic Attempt number and unique SHA-256 Attempt key;
|
|
- mode `LOCAL_H2` and a non-secret sandbox fingerprint;
|
|
- optional `retry_of_attempt_id`;
|
|
- `PENDING`, `RUNNING`, `SUCCEEDED`, `FAILED`, or `ABORTED` state;
|
|
- expected and succeeded Receipt counts;
|
|
- authenticated operator, timestamps, duration, and sanitized terminal error.
|
|
|
|
A replay reference is accepted only when the referenced Attempt belongs to the same Run and is `FAILED` or `ABORTED`. Replay creates a new sandbox and a new Attempt; it never pretends to resume the destroyed in-memory database.
|
|
|
|
`PENDING` and `RUNNING` Attempts can be manually aborted. Mapper updates include current-state predicates, so an abort and a concurrent completion cannot both win.
|
|
|
|
## Scenario Receipts
|
|
|
|
`factory_plugin_delivery_rehearsal_receipt` freezes the Scenario ID, sequence, code, and name for one Attempt. Receipt states are `PENDING`, `RUNNING`, `SUCCEEDED`, `FAILED`, and `ABORTED`.
|
|
|
|
Successful and failed Receipts persist canonical non-secret evidence JSON plus SHA-256. Detail reads verify:
|
|
|
|
- parent Run and Attempt fingerprint binding;
|
|
- Receipt count and ordered Scenario identity;
|
|
- evidence JSON fingerprint;
|
|
- succeeded count and terminal Attempt consistency.
|
|
|
|
Raw evidence JSON is ignored by REST serialization. Parsed evidence is returned only after verification. Pending, running, and aborted Receipts must not contain evidence payloads.
|
|
|
|
## Local H2 Scenarios
|
|
|
|
The Session enforces the six Scenario codes in frozen order:
|
|
|
|
1. **Approval request:** applies the real approval policy to synthetic requester/approver identities, records `PENDING -> APPROVED`, and proves distinct actors, role snapshots, reasons, and expiries.
|
|
2. **Approval expiry:** records an expired request and executes the deadline predicate that transitions it to `EXPIRED`.
|
|
3. **Approval revocation:** records an approved request, validates the revoker role and reason, and transitions it to `REVOKED`.
|
|
4. **Mixed apply:** executes the trusted database baseline through `sql-jdbc:v1`, the permission document through `permission-jdbc:v1`, and the menu document through `menu-jdbc:v1`; then verifies marker, ownership, role grants, and target Receipts.
|
|
5. **Failure retry:** submits an `INSERT IGNORE` into a deliberately absent table. The SQL Executor first leaves a `FAILED` target Receipt, the sandbox creates the missing table, and the exact same contribution and idempotency key are retried. Evidence requires `execution_count=2`, one marker row, and stable duplicate receipt identity.
|
|
6. **Reverse compensation:** runs menu, permission, and SQL rollback in that order. Evidence requires both ownership tombstones to be `REMOVED`, the baseline marker table to be absent, seven succeeded target Receipts, and no remaining failed target Receipt.
|
|
|
|
The H2 URL, internal username, and database name are never persisted or returned. Only the sandbox fingerprint is public.
|
|
|
|
## API And UI
|
|
|
|
All endpoints require `generator:delivery:verify`:
|
|
|
|
- `POST /generator/plugin/delivery-rehearsals/{rehearsalId}/attempts` starts a fresh or linked replay Attempt;
|
|
- `GET /generator/plugin/delivery-rehearsals/{rehearsalId}/attempts` lists summaries;
|
|
- `GET /generator/plugin/delivery-rehearsals/{rehearsalId}/attempts/{attemptId}` verifies and returns evidence;
|
|
- `POST /generator/plugin/delivery-rehearsals/{rehearsalId}/attempts/{attemptId}/abort` aborts an open Attempt.
|
|
|
|
Execution is synchronous in this phase. The delivery report shows Attempt history, progress, replay source, duration, and actions. A separate evidence dialog uses expandable rows so canonical evidence does not overwhelm the operational table.
|
|
|
|
## Security And Boundaries
|
|
|
|
- No arbitrary SQL, document, Plugin code, JDBC URL, or sandbox option comes from the request. The Session resolves only the three installed trusted baseline releases and one platform-owned retry statement.
|
|
- H2 is packaged as a runtime dependency solely for the local rehearsal Session. The normal configured target and its connection factory are not used.
|
|
- Synthetic approval identities prove policy mechanics; they are not real human approval evidence and cannot authorize a Plugin Transition.
|
|
- A process stop can leave an Attempt open in the control database. Because the H2 database is ephemeral, recovery is an explicit abort followed by a fresh Attempt, not same-process continuation.
|
|
- The synchronous API is suitable for the current six short scenarios, not long deployment workloads. Durable asynchronous leasing remains a later stage.
|
|
- No external MySQL instance was connected or modified. Plaintext development credentials and TLS verification remain deferred by explicit user decision.
|