173 lines
15 KiB
Markdown
173 lines
15 KiB
Markdown
# Foundry service integration evidence
|
||
|
||
Status: implementation, service/migration and final acceptance delivery completed.
|
||
Main integration and deployment require separate actions.
|
||
The T01–T36 source/assertion audit and current frontend regression gates have
|
||
passed; see [FINAL_ACCEPTANCE.md](FINAL_ACCEPTANCE.md). Main integration and
|
||
production deployment are separate, pending steps.
|
||
|
||
## Verified revisions and environment
|
||
|
||
- Current verified Endoleap service consumer: `dcbbdad25de7c3b1d6bee317df6074da2c0642eb`
|
||
(product implementation `15ee917`; receipt diagnostics added by `dcbbdad`).
|
||
- Current Foundry: `506f778ac33d47fbd6f38412995a10218d59fe0a`.
|
||
- [Foundry CI #1186](https://gitea.entroia.com/Zayden-Jung/foundry-core/actions/runs/1186):
|
||
job 1283 completed successfully, all seven steps successful. All prior flags
|
||
and `dissolveCanvas`, `dissolveLostAckRecovered`, `dissolveUndoRedo` are true;
|
||
`aiExecutionCount: 3`, 84 transport calls. The new canonical-frame rotation
|
||
test also passed. Same-commit PR CI #1187/job 1284 subsequently passed all seven
|
||
steps, with the same flags/execution count and 83 transport calls.
|
||
- [Foundry CI #1182](https://gitea.entroia.com/Zayden-Jung/foundry-core/actions/runs/1182):
|
||
job 1279 completed successfully, all seven steps successful, pinned to the
|
||
browser delivery baseline `24c4592`, Foundry `5db2bf3`. Its report has all document/resource/AI and
|
||
migration flags true, `aiExecutionCount: 3`, and 75 transport calls.
|
||
Same-commit PR CI #1183/job 1280 subsequently passed all seven steps too.
|
||
- [Foundry CI #1180](https://gitea.entroia.com/Zayden-Jung/foundry-core/actions/runs/1180)
|
||
and [PR CI #1181](https://gitea.entroia.com/Zayden-Jung/foundry-core/actions/runs/1181):
|
||
completed successfully for consumer `26da326` and Foundry `3268c57`;
|
||
jobs 1277/1278, all seven steps successful. The original service scope audit
|
||
also passed CI #1178 and #1179.
|
||
- Existing `ces-control` runner executes Go checks/build, schema migration and
|
||
isolated PostgreSQL integration, then the pinned Node 24 consumer and HTTP smoke
|
||
checks. No local backend build or Docker execution was used.
|
||
- Local frontend: 822 Node tests and full TypeScript checking passed. Tests use
|
||
the source modules; packaged SDK and application delivery remain separate gates.
|
||
|
||
## What the checks actually prove
|
||
|
||
| Requirement | Authoritative entry and observed assertion |
|
||
| --- | --- |
|
||
| Explicit identity migration | `TestCanonicalModelMigrationAndIncrementalLifecycle`: GET does not migrate; retry returns the same identity map; implicit partitions become owning canvases; old snapshot writers are rejected. The real Node consumer also migrates and retries. |
|
||
| Migration admission and late rollback | `TestCanonicalMigrationPermissionVersionAndRunGuards` checks viewer denial, stale source versions, queued/running work and stable negative receipts after conditions change. `TestCanonicalMigrationLateCancellationRollsBack` observes the actual identity-map INSERT blocked after canonical/material/subgraph writes, cancels it, then checks all related rows, original legacy JSON and version before retrying the original key successfully. |
|
||
| Incremental writes and receipt identity | `TestCanonicalModelMigrationAndIncrementalLifecycle` verifies exact retries, unknown receipt semantics, logical ID coverage, participant versions, and zero writes/logical-ID consumption after a later batch condition fails. It checks canonical DB rows, not just HTTP status. |
|
||
| Canonical concurrent writers | `TestCanonicalConcurrentMigrationAndOwnershipWrites` races four identical migrations, then four identical edits, requiring identical receipts and one version advance. Two different requests then compete to move alternate endpoints and their common edge: exactly one wins, the loser has a queryable terminal version-conflict receipt, both canvas versions advance once, and the full ownership graph remains valid. Reusing the winning key with changed bytes is rejected without changing the model. |
|
||
| Dissolve without deleting members | The real consumer creates nested child/grandchild canvases, dissolves the child and loses its successful response. Reopen queries the original request without a second POST. Direct members and the nested entry move to the parent, the leaf retains its grandchild owner/geometry, and the original entry/edge remain. Undo/redo/undo restores the original bindings. This uses the existing atomic edit protocol and the real HTTP/DB service. |
|
||
| Canonical frame geometry | `TestCanonicalFramesRetainRotationAcrossOwnerChanges` preserves nonzero frame rotation through owner changes, projection and an unrelated canonical AI patch, while rejecting 360 degrees. The legacy snapshot writer still rejects rotated frames; its restriction no longer rejects canonical coordinate conversion. |
|
||
| Real frontend coordination | `TestHeadlessClientHTTPIntegration` runs `tests/headless/foundry.integration.mjs` against authenticated HTTP and PostgreSQL. It verifies lost document ACK recovery without duplicate POST, atomic partition edits, deep copy with a parent-owned incoming edge, partial import and old stream-tail coordination. |
|
||
| Resources and authorization | The consumer verifies lost upload ACK, shared pending-image upload, original bytes, metadata, cross-project adoption and reopen. `TestOnboardingAndSharing` additionally revokes source access after warm reads, verifies no target model/version/binding changes, preserves the rejected receipt after permission restoration, and checks independent target access. |
|
||
| AI execution identity and controls | `TestCanonicalAIAdmissionAndLifecycle` covers admission/query/retry, zero-effect rejection, old incarnation callbacks, cancellation, managed image output, owner relocation, archived admission routes and execution after permission revocation. |
|
||
| Actual frontend RunPort | `tests/headless/foundry-ai.integration.mjs` exercises `createFoundryRuns`, the HTTP transport and ProjectEngine: successful admission response loss/reopen/query, queued cancellation response loss, generation-time content conflict, explicit apply response loss plus undo/reopen/redo, generated image metadata/original bytes/preview, and copy without a new run or upload. |
|
||
| Host identity migration coordination | `canvas-migration.ts` now drives the real consumer's initial migration: the server commits, the response is lost, a new coordinator reads the stored body/key and queries the original receipt without a second POST. A later intentional raw POST still checks backend idempotent retry. The coordinator's drain and lock ports are fixtures here; this does not prove the old editor's browser handoff gate is connected. |
|
||
| Browser legacy handoff | `renderer.integration.mjs --migration-only` exercises the actual GraphPage, legacy editor, upgrade panel and Next proxy with native Chrome input, localStorage and Web Locks. Dirty old PATCH ACK precedes migration; another editable view excludes migration; committed response loss survives reload without a second migration POST; uncommitted response loss reuses the original body/key, with terminal rejection followed by explicit fresh preparation; a different cached draft must be explicitly restored before migration. A draft modal cannot block receipt recovery; it becomes actionable after terminal rejection. The upstream is a protocol fixture, not the real Foundry service. |
|
||
|
||
The CI #1174 consumer report contains `status: "ok"`, 72 HTTP transport calls,
|
||
all 14 prior document/resource flags true, plus `runtimeAI`, `aiLostAdmission`,
|
||
`aiCancelReconciled`, `aiConflictApplyUndo`, `aiManagedImage`, `aiCopyNoRun` true.
|
||
`aiExecutionCount` is exactly 3: text, retained conflict output, image. The queued
|
||
cancelled run never calls generation. Preview fetching is a separate authenticated
|
||
host fetch and is not included in the 72 transport calls.
|
||
CI #1178 repeated the same pinned consumer successfully with 71 transport calls
|
||
and the same flags/execution count. Timing-dependent poll counts are observations,
|
||
not an exact total-call contract; admission/action/upload duplication has separate
|
||
explicit assertions.
|
||
CI #1180 additionally reports `migrationCoordinator` and
|
||
`migrationLostAckRecovered` true, with 76 transport calls and the same document,
|
||
resource and AI results. The local coordinator suite covers 11 cases, including
|
||
quota/no-write behavior, uncommitted-request recovery, invalid receipt retention,
|
||
identity/abort fences and terminal rejection followed by explicit preparation.
|
||
|
||
## Issues exposed by the real consumer
|
||
|
||
1. The standalone AI client omitted the v2 Accept header. The Next proxy had
|
||
supplied it, hiding the omission in application-only testing. `canvas-v2`
|
||
negotiation now belongs to the AI adapter and shared transport; regression
|
||
tests cover all three writes and receipt queries with original body/key/version.
|
||
2. Asset display URLs assumed the application's relative preview route. The
|
||
asset adapter now accepts a host `displayURL(id)` callback. Canonical source
|
||
identity and authority remain separate; preview bytes are not used as original
|
||
file digest evidence. Authentication stays in the host fetch/transport.
|
||
3. CI #1184/#1185 rejected the nested creation before reaching dissolution:
|
||
canonical validation had copied the legacy frame's zero-rotation rule. A
|
||
rotated owner can require a frame to retain nonzero rotation after conversion.
|
||
Foundry `506f778` removes that canonical-only restriction; existing finite/range
|
||
checks and legacy normalization remain. The consumer now checks the creation
|
||
receipt before reading descendants, so a rejection reports its actual state.
|
||
|
||
The test harness also needed working controlled timers, a cancelled run's final
|
||
event drain before the next admission, and actual copy-source file persistence.
|
||
The adoption stage still asserts zero project-local file writes. The subsequent
|
||
copy stage permits source checkpoints but rejects bitmap file duplication and
|
||
asserts no extra upload or generation. Those fixes do not bypass busy, cursor,
|
||
durability or resource-sharing checks.
|
||
|
||
## Final-audit recovery cuts
|
||
|
||
`crash-windows.test.mjs` selects actual immutable cuts produced by the engine:
|
||
before local durability, durable pending intent, frozen request, dispatch-marked
|
||
before server commit, dispatch-marked after server commit, and durable receipt/base.
|
||
Each independent recovery pairs that cut with its corresponding server/receipt
|
||
state, then checks document/history/logical IDs, exact frozen request bytes,
|
||
POST/query counts and final durability. Frozen recovery may conservatively query
|
||
before its exact retry; a missing receipt never creates a new identity. These are
|
||
memory StoragePort/protocol fixtures, not physical browser-process termination.
|
||
Actual IndexedDB atomic rollback, fencing/checksum/journal-gap and reopening
|
||
evidence remains the separate browser suite; this is not every possible cross-product.
|
||
|
||
`engine.test.mjs` additionally commits a create, loses its ACK, deletes locally,
|
||
reopens, queries the original create and finally sends the dependent deletion.
|
||
The server has no residual element; both original history units remain and the
|
||
creation is not submitted twice. The focused engine/crash suite passes 36 tests;
|
||
the full Node suite passes 821. `resources.test.mjs` also verifies replacement of
|
||
an existing image while the new upload is gated: the old server reference stays
|
||
valid, undo prevents a late replacement, and redo/reopen reuse the two uploaded
|
||
resources without a new upload or element incarnation. Its 32 checks pass.
|
||
The subsequent T01–T36 audit is recorded in `FINAL_ACCEPTANCE.md`; the final
|
||
frontend run passes 822 Node tests, with both 51-check browser bundlers, 10 hooks,
|
||
57 browser-storage checks, 6 proxy checks, both five-scenario migration entries
|
||
and the 270-file unpacked package passing.
|
||
|
||
## Boundaries and remaining audit
|
||
|
||
The recovery store is an in-memory durable-batch fixture, and response loss is
|
||
injected after successful HTTP responses. Real IndexedDB/Web Locks/browser
|
||
acceptance is recorded separately in `STEP4_ACCEPTANCE.md`; this service run does
|
||
not combine every browser crash window with every server operation.
|
||
The migration coordinator uses a string-storage port before a canonical engine
|
||
exists. `browser-canvas-migration.ts` supplies localStorage, identity fences and
|
||
workspace-scoped native Web Locks. Every editable legacy view holds a shared
|
||
lease; upgrade first freezes and drains its writer, releases that lease, then
|
||
takes the exclusive lease and prepares again before creating a request. Pending
|
||
records block affected legacy views across reload. Unknown results retain the
|
||
original request; only a verified terminal rejection permits fresh preparation.
|
||
Upload/import/member-task and draft-recovery gates preserve the old editor's
|
||
content rather than converting in-memory work silently. A differing cached draft
|
||
is surfaced for explicit recovery, and the current draft is backed up before
|
||
waiting for its PATCH ACK. The account fence also covers old snapshot requests.
|
||
|
||
The browser fixture above proves the connected UI path, including actual native
|
||
locking, and the separate real-service consumer proves server coordination.
|
||
They do not combine a real browser and real PostgreSQL in one scenario. Full
|
||
webpack and Turbopack application regressions each passed 51 checks; the migration
|
||
entry adds five scenarios and three lock-lifetime unit tests. Unknown
|
||
receipt/error states remain read-only with an export action. Unsupported Web
|
||
Locks prevents upgrading, while existing legacy editing remains available when
|
||
there is no pending migration. The stage 6 audit also inspected source/package
|
||
exports, peer dependencies and documentation targets, then passed the actual
|
||
267-file unpacked package's Node/types, framework-peer, compiled browser storage
|
||
and Worker checks. Together with CI #1182 and both browser bundlers this closes
|
||
stage 6. The final requirement matrix is recorded separately; the two new scheduler
|
||
clock-shift checks cover backward/forward wall time, dependency/unknown claims,
|
||
stale timer callbacks and remaining wait calculation after recovery.
|
||
|
||
`canvas_headless_worker_integration_test.go` supplies deterministic generation
|
||
output over the actual worker HTTP protocol. Admission, claim, events, canonical
|
||
writes, image storage and action receipts use the real service/DB. Private worker
|
||
controls are registered only in the test assembly. Production's background queue
|
||
loop, external model availability, provider billing and real CLI authentication
|
||
are not proved by that fixture. `TestCanvasAIRealWorker` remains opt-in and skipped.
|
||
|
||
The CI log includes an early skip of `TestHeadlessClientHTTPIntegration` without
|
||
its opt-in environment and a later successful execution in the explicit Node/DB
|
||
phase. Those are different invocations. The latest successful log has 158 distinct PASS names
|
||
including subtests; that count is not 154 independent end-to-end scenarios.
|
||
|
||
The service audit covers the original stage requirements: target incremental and
|
||
idempotent protocols, frontend/runtime/resource adapters, explicit legacy
|
||
compatibility, identity mapping, source-version/permission/run admission barriers,
|
||
and rollback after writes have begun. Migration/delivery now has the separate
|
||
browser/package evidence above; the final requirement matrix now has its separate per-row audit. A green
|
||
feature-branch run does not merge or deploy
|
||
either repository. [Foundry PR #19](https://gitea.entroia.com/Zayden-Jung/foundry-core/pulls/19)
|
||
is open, ready for review (`draft: false`, `mergeable: true`, checked 2026-11-11),
|
||
and waits for the user to merge manually.
|