feat(data): discover public events via the global index (not fan-out)
On creating a public event, Festipod submits it to the discovery index (an SDK call); the discovery screen reads the index instead of enumerating accounts. The app knows nothing of the index's owner, inbox, or materialization — it treats the lib as a finished SDK whose discovery is a global index. No store ids. Unit-validated in the lib (79 tests). @data broker validation deferred: the NextGraph broker (nextgraph.net/eu) was unreachable at run time — to be re-run in T03.d once the broker recovers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -361,29 +361,44 @@ function ConnectedHarness() {
|
||||
return { docA, docB, listed };
|
||||
},
|
||||
|
||||
// --- Public discovery cross-accounts (T02.e) -----------------------
|
||||
// --- Public discovery via the GLOBAL INDEX (T03.c) -----------------
|
||||
// Product-level scenario: a PUBLISHER account creates its own PUBLIC
|
||||
// event document (createEntityDoc → makePublic via caps.open); a
|
||||
// separate, NON-connected DISCOVERER account then materializes the
|
||||
// cross-account public source (allAccounts → listEntityDocs('public'))
|
||||
// and reads the event via a real useShape({graphs}). No friendship/
|
||||
// connection is ever declared between them — discovery is by the public
|
||||
// fan-out alone. Returns the publisher's doc + the discovered index.
|
||||
// event document and SUBMITS its reference to the SDK global discovery
|
||||
// index (submitEventToIndex). A separate, NON-connected DISCOVERER
|
||||
// account then READS THE INDEX (readDiscoveredEvents) — deposit →
|
||||
// materialize → read — and subscribes to the referenced document via a
|
||||
// real useShape({graphs}). No friendship/connection is ever declared
|
||||
// between them, and NO cross-account fan-out is used — discovery goes
|
||||
// through the index alone. Returns the publisher's doc + the index refs.
|
||||
// <FanoutProbe> is reused to mount the multi-graph subscription; the
|
||||
// event is written into the publisher doc before the reader lists it.
|
||||
async publishPublicEventAs(publisher: string, title: string) {
|
||||
const reg = await import('../utils/storeRegistry');
|
||||
const disc = await import('../data/discovery');
|
||||
reg.resetRegistryCache();
|
||||
await reg.ensureAccount(publisher);
|
||||
const doc = await reg.createEntityDoc(publisher, 'public');
|
||||
// Make it discoverable: submit the event reference to the global index.
|
||||
await disc.submitEventToIndex({ doc, id: doc, title }, publisher);
|
||||
return { doc };
|
||||
},
|
||||
async discoverPublicEventsAs(discoverer: string) {
|
||||
const reg = await import('../utils/storeRegistry');
|
||||
const disc = await import('../data/discovery');
|
||||
// The discoverer account exists but is NOT connected to the publisher.
|
||||
await reg.ensureAccount(discoverer);
|
||||
reg.resetRegistryCache();
|
||||
const listed = await reg.listEntityDocs('public'); // cross-account
|
||||
// Read the GLOBAL INDEX (not a cross-account fan-out) to discover. The
|
||||
// submit deposit needs a moment to land in the broker's queryable graph
|
||||
// (same lag as any inbox deposit), so poll the index (bounded) until an
|
||||
// entry appears before mounting the multi-graph subscription.
|
||||
let listed: string[] = [];
|
||||
for (let i = 0; i < 20 && listed.length === 0; i++) {
|
||||
const refs = await disc.readDiscoveredEvents();
|
||||
listed = [...new Set(refs.map(r => r.doc).filter(Boolean))];
|
||||
if (listed.length) break;
|
||||
await new Promise(r => setTimeout(r, 250));
|
||||
}
|
||||
setFanoutGraphs(listed);
|
||||
return { listed };
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user