auth-yes/docs/superpowers/plans/2026-08-25-ephemeral-passes-and-multi-claim-events.md

8.3 KiB

Ephemeral Magic Passes & Multi-Claim Event Passes Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Implement 1-on-1 Ephemeral Magic Links, Multi-Claim Event/Workshop Passes (with short codes, PINs, short URLs, and CLI 1-liners), and a real-time Event Cockpit with a master kill switch.

Architecture: Extend the Auth-Yes zero-trust session engine with a dedicated event registry in PostgreSQL and Valkey. Provide a unified 1-click redemption endpoint (GET /pass), a short-code/PIN join portal (GET /join, GET /e/:slug), CLI environment streams (GET /join/:slug?format=env), and live seat metrics with sub-millisecond batch revocation via Valkey RESP3 push tracking.

Tech Stack: Deno 2.x, TypeScript 5.x, Hono SSR JSX (React-free), PostgreSQL 18, Valkey 8, Traefik ForwardAuth.

Spec: DUAL_AUDIENCE_DEVELOPMENT_GUIDE.md

Global Constraints

  • Strictly zero React dependencies; use pure Hono SSR JSX.
  • Zero-dependency SDK in sdk/.
  • All cookie mutations must delete host-only cookies and set wildcard .atyg.org domain cookies.
  • Every commit and change must be pushed to both GitHub (origin) and Gitea (gitea).
  • Quality gates must pass: deno fmt, deno task lint, deno task check, deno task test.

Files:

  • Modify: server/main.ts
  • Modify: ui/components/SessionsPage.tsx
  • Test: server/main.test.ts

Interfaces:

  • Consumes: extractAllSessionIds(c), valkey.get(), sqlWrapper.sql

  • Produces: GET /pass?token=... endpoint and updated Hand-Off Modal in SessionsPage.tsx

  • Step 1: Write the failing test for GET /pass

// in server/main.test.ts
Deno.test("GET /pass - Ephemeral Magic Link 1-Click Redemption", async (t) => {
  await t.step(
    "Valid token sets wildcard cookie and redirects to target app",
    async () => {
      const valkeyStub = stub(valkey, "get", (key: any) => {
        if (String(key) === "ay_sess_valid_pass") {
          return Promise.resolve(
            JSON.stringify({
              uuid: "guest-uuid",
              username: "guest_user",
              customScopes: ["app:ed-droid"],
            }),
          );
        }
        return Promise.resolve(null);
      });

      const originalSql = sqlWrapper.sql;
      sqlWrapper.sql = ((_query: any) => {
        return Promise.resolve([{ domain: "ed-droid.atyg.org" }]);
      }) as any;

      try {
        const res = await app.request("/pass?token=ay_sess_valid_pass", {
          method: "GET",
        });
        assertEquals(res.status, 302);
        const setCookie = res.headers.get("set-cookie") || "";
        assert(setCookie.includes("session_id=ay_sess_valid_pass"));
        assert(
          res.headers.get("location")?.includes("ed-droid.atyg.org") ||
            res.headers.get("location") === "/dashboard",
        );
      } finally {
        sqlWrapper.sql = originalSql;
        valkeyStub.restore();
      }
    },
  );
});
  • Step 2: Run test to verify it fails Run: deno test server/main.test.ts --filter "Ephemeral Magic Link" Expected: FAIL (404 Not Found on /pass)

  • Step 3: Implement GET /pass in server/main.ts Extract token from ?token=..., validate against Valkey/DB, set cookie with getCookieDomain(), resolve target app domain if scoped to a specific app, and return c.redirect(targetUrl).

  • Step 4: Update ui/components/SessionsPage.tsx Add the "1-Click Magic Link" copy card tab alongside the CLI and cURL header tabs.

  • Step 5: Run tests to verify they pass Run: deno task test Expected: PASS (All tests passing)

  • Step 6: Commit and Push

git add server/main.ts server/main.test.ts ui/components/SessionsPage.tsx
git commit -m "feat(pass): implement 1-click ephemeral magic link redemption route"
git push origin main && git push gitea main

Task 2: Multi-Claim Event Passes Schema & Join Endpoints (/join, /e/:slug, CLI 1-Liner)

Files:

  • Modify: server/db.ts
  • Modify: server/main.ts
  • Create: ui/components/EventJoinPage.tsx
  • Create: ui/components/EventSplashPage.tsx
  • Test: server/main.test.ts

Interfaces:

  • Produces:

    • Table: event_passes in PostgreSQL
    • Endpoints:
      • POST /api/events: Create event pass (slug, pin_code, name, max_seats, lifespan_hours, app_id, role)
      • GET /e/:slug: Web landing splash with "Enter Workshop" action
      • GET /join: Universal PIN / word-code entry page
      • POST /api/join: Redeems code/PIN and creates isolated guest_<slug>_<index> session
      • GET /join/:slug: CLI 1-liner (?format=env or ?format=json)
  • Step 1: Write the failing tests for Event creation and redemption

Deno.test("Multi-Claim Event Passes & Join Endpoints", async (t) => {
  await t.step("POST /api/events creates an event pass", async () => {
    // Test event creation
  });
  await t.step("POST /api/join provisions an isolated guest seat", async () => {
    // Test seat provisioning
  });
  await t.step("GET /join/:slug?format=env returns shell export", async () => {
    // Test CLI 1-liner
  });
});
  • Step 2: Run test to verify it fails Run: deno test server/main.test.ts --filter "Multi-Claim Event" Expected: FAIL

  • Step 3: Add event_passes schema in server/db.ts Include columns: id, slug, pin_code, name, app_id, role, max_seats, seats_claimed, lifespan_hours, created_by, is_active, expires_at, created_at.

  • Step 4: Implement Event API routes in server/main.ts and SSR UI Pages

  • Create ui/components/EventJoinPage.tsx for /join PIN code entry.

  • Create ui/components/EventSplashPage.tsx for /e/:slug 1-click workshop entrance.

  • Implement GET /join/:slug returning export AUTH_YES_TOKEN="..." when ?format=env.

  • Step 5: Run tests to verify they pass Run: deno task test Expected: PASS

  • Step 6: Commit and Push

git add server/db.ts server/main.ts ui/components/EventJoinPage.tsx ui/components/EventSplashPage.tsx server/main.test.ts
git commit -m "feat(events): implement multi-claim event passes, PIN join portal, and CLI 1-liner"
git push origin main && git push gitea main

Task 3: Live Event Cockpit & Master Kill-Switch

Files:

  • Modify: server/main.ts
  • Modify: ui/components/SessionsPage.tsx
  • Modify: ui/mod.ts
  • Test: server/main.test.ts

Interfaces:

  • Produces:

    • POST /api/events/:id/end: Closes event and immediately revokes all guest sessions
    • POST /api/events/:id/extend: Adds hours to active event
    • Event Management Deck in SessionsPage.tsx with live seat counter (38 / 50) and master kill switch
  • Step 1: Write failing tests for Event Kill-Switch & Extension

Deno.test("Event Cockpit & Master Kill Switch", async (t) => {
  await t.step(
    "POST /api/events/:id/end revokes all guest seats instantly",
    async () => {
      // verify sessions deleted and Valkey cleared
    },
  );
});
  • Step 2: Run test to verify it fails Run: deno test server/main.test.ts --filter "Event Cockpit" Expected: FAIL

  • Step 3: Implement POST /api/events/:id/end and POST /api/events/:id/extend in server/routes/events.ts Fetch all session IDs created under the event pass, delete them from Valkey and PostgreSQL, record in audit ledger, and mark event is_active = false.

  • Step 4: Update ui/components/SessionsPage.tsx with Event Cockpit Deck Display active events with live progress bar (Seats Claimed / Capacity), PIN badge, copy links, [+1h Extend] and [🔴 End Workshop & Revoke All].

  • Step 5: Run full quality gates Run: deno fmt && deno task lint && deno task check && deno task test Expected: All pass.

  • Step 6: Commit and Push

git add server/routes/events.ts ui/components/SessionsPage.tsx ui/mod.ts server/main.test.ts
git commit -m "feat(cockpit): add live event metrics, seat roster, and master kill-switch"
git push origin main && git push gitea main