Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions e2e/cohort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
// minted-account run — i.e. it carries a mint token (E2E_ACCOUNT_TOKEN, used by
// the CI workflow to mint/reap the account) or an already-minted session JWT
// (E2E_SESSION_JWT). A prod target WITHOUT either is still refused, so a stray /
// mis-configured invocation can never provision-and-leak against prod.

Check warning on line 91 in e2e/cohort.ts

View workflow job for this annotation

GitHub Actions / typos

"mis" should be "miss" or "mist".

/** The prod api host. A prod target is only allowed for a sanctioned minted run. */
export const PROD_API_HOST = 'api.instanode.dev'
Expand Down Expand Up @@ -273,14 +273,21 @@
* Resolve the provision identity for a LIVE resource spec. Prefers the minted
* pro account (authed) when E2E_SESSION_JWT is set; else the anon bypass path.
*
* `forceAnon` pins the anonymous bypass path even when a minted session exists.
* Used for the QUEUE flow: the authed (pro) /queue/new path attempts isolated
* per-tenant NATS provisioning, which HANGS on prod until the operator seeds the
* NATS operator/sys NKeys (CLAUDE.md P1 known gap). The anonymous path returns
* fast with auth_mode=legacy_open. The resulting anon resource is reaped by its
* 24h TTL (no authed DELETE exists for anon resources); the spec treats a
* no-bearer resource's reap as best-effort (TTL-backed) rather than asserting a
* 200 it can never get.
* `forceAnon` pins the anonymous fast-hot-pool path even when a minted session
* exists. Used wherever the AUTHED prod provision is too slow / hangs to finish
* inside the LIVE per-test timeout (playwright.live.config.ts, 90s):
* - DB & VECTOR: the authed (pro) /db/new & /vector/new paths provision a
* DEDICATED Postgres / pgvector Postgres for the team — slow on prod (15s
* warm, >90s cold). The anon path uses the fast (pgvector) hot-pool.
* - QUEUE: the authed /queue/new isolated per-tenant NATS path HANGS on prod
* until the operator seeds the NATS operator/sys NKeys (CLAUDE.md P1 known
* gap). The anon path returns fast with auth_mode=legacy_open.
* In every forceAnon case the resulting anon resource is reaped by its 24h TTL
* (no authed DELETE exists for anon resources); the spec treats a no-bearer
* resource's reap as best-effort (TTL-backed) rather than asserting a 200 it can
* never get. The genuinely-fast services (cache/nosql/storage/webhook) stay on
* the authed-minted path so the authed/minted-account + authed-reap legs are
* still exercised.
*/
export function provisionIdentity(
extra: Record<string, string> = {},
Expand Down
35 changes: 35 additions & 0 deletions e2e/live-anon-provision.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,47 @@ interface ProvisionFlow {
// The registry. The matrix's seventh service (db) is covered by
// live-provision-smoke.spec.ts; the six below complete the set. Editing this
// table is the ONLY change needed to add/remove a covered service.
//
// ── Per-service provision-path choice (forceAnon vs authed-minted) ────────────
// Each flow runs as EITHER the minted PRO account (authed, exercises the
// minted-account/authed-reap path) OR the anonymous fast-hot-pool path
// (forceAnon). The deciding factor is whether the AUTHED prod provision is fast
// enough to finish inside the 90s per-test timeout (playwright.live.config.ts):
//
// service | path | why
// ---------|----------------|----------------------------------------------
// db | anon (forceAnon, in smoke spec) | authed = DEDICATED Postgres,
// | | cold-provision > 90s on prod; anon = hot-pool (fast)
// vector | anon (forceAnon)| authed = DEDICATED pgvector Postgres, same
// | | slow dedicated-provision as db (15s warm, >90s
// | | cold) → TIMED OUT the suite (run 26999448643).
// | | anon = fast hot-pool; anon resource TTL-reaped.
// queue | anon (forceAnon)| authed isolated-NATS path HANGS on prod (P1
// | | NKeys gap); anon returns fast (legacy_open).
// cache | authed-minted | Redis provision is fast (no dedicated DB build);
// | | KEEPS authed/minted-account + authed-reap coverage.
// nosql | authed-minted | Mongo provision is fast; KEEPS authed coverage.
// storage | authed-minted | DO Spaces tenant-prefix (no DB build) → fast;
// | | KEEPS authed coverage.
// webhook | authed-minted | Redis-backed receiver, fast; KEEPS authed coverage.
//
// Net: the two genuinely-slow DEDICATED-DB provisions (db, vector) and the
// hanging queue path use the fast anon hot-pool so they can NEVER exceed the
// timeout; cache/nosql/storage/webhook still exercise the authed/minted-account
// (and authed-reap) path. That keeps both paths covered with zero flake.
const PROVISION_FLOWS: ProvisionFlow[] = [
{
label: 'vector',
path: '/vector/new',
connKey: 'connection_url',
connPattern: /^postgres(ql)?:\/\//,
// Pin anon: the authed (pro) /vector/new path provisions a DEDICATED
// pgvector Postgres for the team — slow on prod (15s warm, >90s cold), which
// timed out the suite at the 90s per-test limit (flaky run 26999448643). The
// anon path uses the fast pgvector hot-pool and returns quickly; the anon
// resource is TTL-reaped (no authed DELETE for anon resources). Same
// treatment as /db/new (smoke spec) — both are dedicated-DB provisions.
forceAnon: true,
extra: (b) =>
expect(b.extension, 'vector provision echoes pgvector extension').toBe('pgvector'),
},
Expand Down
Loading