Server-side realtime SSE on per-app pub/sub topics, plus the three
v1.1.5 follow-ups and the version bumps.
Realtime:
- topics registry (0021) + admin endpoints + Capability::AppTopicManage
(-> app:admin; no new scope).
- GET /realtime/topics/{topic} SSE endpoint (orchestrator-core data
plane): Host -> app, RealtimeAuthority gate (404 missing/internal,
401 bad/absent token), broadcast::Receiver stream + heartbeat.
- RealtimeBroadcaster / RealtimeEvent / RealtimeAuthority traits
(picloud-shared); InProcessBroadcaster + GC (orchestrator-core);
DB-backed RealtimeAuthorityImpl (manager-core). Publish path fans out
to in-process subscribers after the durable outbox commit (best-effort,
panic-isolated).
- HMAC subscriber tokens (subscriber_token.rs) + app_secrets table (0022)
+ pubsub::subscriber_token SDK (schema 1.6 -> 1.7). TTL clamp + env
overrides.
- Dashboard Topics tab (register/list/edit/delete, prominent external
badge, flip confirmation).
v1.1.5 follow-ups:
- Empty blobs accepted (NewFile/FileUpdate::validate) + round-trip test.
- Orphan *.tmp.* sweeper (spawn_files_orphan_sweep).
- Dispatcher e2e tests, one per trigger kind (DATABASE_URL-gated).
Versions: workspace 1.1.6, SDK 1.7, dashboard 0.12.0. Schema-snapshot
golden re-blessed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
20 lines
959 B
SQL
20 lines
959 B
SQL
-- v1.1.6: per-app secret material. Currently holds the HMAC signing key
|
|
-- used to mint + verify realtime subscriber tokens
|
|
-- (pubsub::subscriber_token → SSE /realtime/topics handshake).
|
|
--
|
|
-- The key is:
|
|
-- * stable across restarts (issued tokens stay valid until expiry),
|
|
-- * per-app (a token signed by app A is rejected by app B),
|
|
-- * never script-accessible (scripts can't print/exfiltrate it — the
|
|
-- SDK only mints tokens, it never returns the key).
|
|
--
|
|
-- The row is created lazily on the first pubsub::subscriber_token call
|
|
-- for an app (32 random bytes). This table is the natural home for
|
|
-- v1.1.7's encrypted per-app secrets work.
|
|
CREATE TABLE app_secrets (
|
|
app_id UUID PRIMARY KEY REFERENCES apps(id) ON DELETE CASCADE,
|
|
realtime_signing_key BYTEA NOT NULL, -- 32 random bytes
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|