test/docs(shared-topics): dispatch test + journey + docs (D2)

Deterministic manager-core test (tests/shared_topics.rs) proves the
namespace boundary both ways: a shared publish fans out only to the
group's shared pubsub trigger (not a per-app or non-shared group
template), and a per-app publish never hits the shared trigger. CLI
journey (shared_topics) covers authoring + `pic triggers ls --group`
shared column + the two validation rejections (undeclared topic; shared
on an app), mirroring the shared_triggers norm. Docs: CLAUDE.md + design
doc §11.6 record D1 + D2 as shipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-02 21:54:32 +02:00
parent 9626d15863
commit 19ba6dbfb4
5 changed files with 401 additions and 3 deletions

View File

@@ -1193,8 +1193,21 @@ Resolved items now live inline next to their topic. What genuinely remains:
> kind, or an undeclared collection. Read-only `shared` column in `pic triggers ls --group`; pinned by
> `tests/shared_triggers.rs` + the `shared_triggers` journey.
>
> **Deferred (documented gaps):** shared **pubsub** triggers (no shared topic store yet); **topics/queue**
> shared collections (trigger-centric, same gap); per-group total-size quotas + write-rate limits;
> **Shipped — D2 shared TOPICS + shared pub/sub triggers.** A group declares a **storeless** `topic`
> shared collection (`group_collections.kind` widened to `topic`+`queue`, `0064`); a
> `[[triggers.pubsub]] shared = true` handler watches it. Scripts publish via the explicit
> `pubsub::shared_topic("events").publish("created", msg)` handle → `GroupPubsubServiceImpl` resolves the
> owning group (kind `topic`) from `cx.app_id`'s chain, requires editor+ (`GroupPubsubPublish`, fails
> closed on anon — a publish is a shared write), and fans out via `PubsubRepo::fan_out_shared_publish` to
> `shared = true` pubsub triggers on that group, each outbox row stamped the WRITER `app_id` (M2 model).
> The per-app `fan_out_publish` gained `AND t.shared = FALSE`, and `validate_bundle_for` requires the
> topic pattern's ROOT segment (`events.*` → `events`) be a declared `kind='topic'` collection
> (group-only) — the `shared` flag + owning-group chain walk are the isolation boundary. No message store
> (topics are events, not persistence). Pinned by `tests/shared_topics.rs` + the `shared_topics` journey.
>
> **Deferred (documented gaps):** shared-topic external SSE subscription; **queue** shared collections
> (D3, competing per-descendant consumers over a group-keyed store); per-group total-size quotas +
> write-rate limits;
> CAS/`set_if`; an operator admin API for shared blobs (scripts use the SDK; `pic collections ls` shows
> the marker — matches KV/docs); app-declared collections. Multi-node tree-apply leans on the runtime
> backstop for no-op edges, as elsewhere.