feat(iios): policy-enforced membership + threaded replies + dev IdP (generic)
Enriches the platform PLANE, not the kernel: - DevOpaPort: the dev OPA stub now evaluates a small policy table (behind the same opa.decide) — DM capped at 2, add-participant requires member/group-admin, governed self-join for membership threads. Real OPA swaps in unchanged. - Dev IdP login (POST /v1/dev/login) issues the same JWT claims a real IdP would. - PolicyDeniedFilter maps fail-closed denials to HTTP 403. Generic kernel additions (no chat vocabulary — 'dm'/'group' live only as OPA policy + an opaque thread attribute): - MessageService.addParticipant (governed membership by userId), governed openThread self-join (scoped to threads with a membership attribute), parentInteractionId on send (reply link), and a generic listThreads. - REST: GET /v1/threads, POST /v1/threads, POST /v1/threads/:id/participants; socket add_participant + membership/parentInteractionId. ensureParticipant gains a role. Tests: dev-opa.port.spec + message.spec (DM cap / group admin / governed join / listThreads / reply). smoke-membership.mjs; realtime smokes updated for governed join. 175 unit tests + all smokes green; kernel free of dm/group literals. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -44,10 +44,11 @@ const alice = connect('alice');
|
||||
const bob = connect('bob');
|
||||
|
||||
try {
|
||||
// Alice creates a thread; Bob joins it.
|
||||
// Alice creates a thread; membership is governed, so Alice ADDS Bob (he can't self-join).
|
||||
const opened = await alice.emitWithAck('open_thread', {});
|
||||
const threadId = opened.threadId;
|
||||
assert(!!threadId, `Alice created thread ${threadId}`);
|
||||
await alice.emitWithAck('add_participant', { threadId, userId: 'bob' });
|
||||
await bob.emitWithAck('open_thread', { threadId });
|
||||
|
||||
// Alice sends; Bob should receive it live.
|
||||
|
||||
Reference in New Issue
Block a user