15 KiB
Foundry service integration evidence
Status: steps 5 (service) and 6 (migration/delivery) completed; overall progress is 6/7. The T01–T36 source/assertion audit and current frontend regression gates have passed; see FINAL_ACCEPTANCE.md. Main integration and production deployment are separate, pending steps.
Verified revisions and environment
- Current verified Endoleap service consumer:
dcbbdad25de7c3b1d6bee317df6074da2c0642eb(product implementation15ee917; receipt diagnostics added bydcbbdad). - Current Foundry:
506f778ac33d47fbd6f38412995a10218d59fe0a. - Foundry CI #1186:
job 1283 completed successfully, all seven steps successful. All prior flags
and
dissolveCanvas,dissolveLostAckRecovered,dissolveUndoRedoare 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:
job 1279 completed successfully, all seven steps successful, pinned to the
browser delivery baseline
24c4592, Foundry5db2bf3. 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
and PR CI #1181:
completed successfully for consumer
26da326and Foundry3268c57; jobs 1277/1278, all seven steps successful. The original service scope audit also passed CI #1178 and #1179. - Existing
ces-controlrunner 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
- The standalone AI client omitted the v2 Accept header. The Next proxy had
supplied it, hiding the omission in application-only testing.
canvas-v2negotiation now belongs to the AI adapter and shared transport; regression tests cover all three writes and receipt queries with original body/key/version. - 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. - 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
506f778removes 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 remains open; readiness is updated after final delivery checks, and merging requires the user’s manual action.