@kubun/plugin-p2p 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/lib/context/delegation.js +130 -1
  2. package/lib/context/group.js +1319 -1
  3. package/lib/context/hub.js +150 -1
  4. package/lib/context/join.js +80 -1
  5. package/lib/context/sync.js +19 -1
  6. package/lib/context/types.d.ts +12 -3
  7. package/lib/context/types.js +28 -1
  8. package/lib/groups/admin-roster.d.ts +130 -0
  9. package/lib/groups/admin-roster.js +184 -0
  10. package/lib/groups/broadcast-codec.js +6 -1
  11. package/lib/groups/broadcast.d.ts +122 -38
  12. package/lib/groups/broadcast.js +627 -1
  13. package/lib/groups/circle-projection.d.ts +122 -0
  14. package/lib/groups/circle-projection.js +288 -0
  15. package/lib/groups/circle-reducers.d.ts +178 -0
  16. package/lib/groups/circle-reducers.js +198 -0
  17. package/lib/groups/events.d.ts +7 -2
  18. package/lib/groups/events.js +10 -1
  19. package/lib/groups/group-anchor.d.ts +63 -0
  20. package/lib/groups/group-anchor.js +107 -0
  21. package/lib/groups/group-crypto.d.ts +19 -0
  22. package/lib/groups/group-crypto.js +85 -0
  23. package/lib/groups/group-handle-registry.d.ts +69 -2
  24. package/lib/groups/group-handle-registry.js +243 -1
  25. package/lib/groups/group-handlers.d.ts +29 -0
  26. package/lib/groups/group-handlers.js +92 -0
  27. package/lib/groups/group-health-monitor.d.ts +56 -0
  28. package/lib/groups/group-health-monitor.js +139 -0
  29. package/lib/groups/group-mls.d.ts +35 -0
  30. package/lib/groups/group-mls.js +164 -0
  31. package/lib/groups/group-peer-manager.d.ts +108 -0
  32. package/lib/groups/group-peer-manager.js +344 -0
  33. package/lib/groups/group-protocols.d.ts +297 -0
  34. package/lib/groups/group-protocols.js +174 -0
  35. package/lib/groups/invite-payload.d.ts +1 -1
  36. package/lib/groups/invite-payload.js +26 -1
  37. package/lib/groups/join-utils.d.ts +1 -0
  38. package/lib/groups/join-utils.js +104 -1
  39. package/lib/groups/ledger-affected-events.d.ts +15 -0
  40. package/lib/groups/ledger-affected-events.js +96 -0
  41. package/lib/groups/ledger-entry.d.ts +37 -0
  42. package/lib/groups/ledger-entry.js +56 -0
  43. package/lib/groups/ledger-fold.d.ts +56 -0
  44. package/lib/groups/ledger-fold.js +53 -0
  45. package/lib/groups/manager.d.ts +29 -71
  46. package/lib/groups/manager.js +281 -1
  47. package/lib/groups/mls-codec.d.ts +1 -1
  48. package/lib/groups/mls-codec.js +18 -1
  49. package/lib/groups/mls-encryptor.d.ts +2 -2
  50. package/lib/groups/mls-encryptor.js +30 -1
  51. package/lib/groups/mls-group-handle.d.ts +1 -1
  52. package/lib/groups/mls-group-handle.js +10 -1
  53. package/lib/groups/mls-json.js +17 -1
  54. package/lib/groups/mls-receive-errors.d.ts +29 -0
  55. package/lib/groups/mls-receive-errors.js +42 -0
  56. package/lib/groups/mls-state.d.ts +1 -1
  57. package/lib/groups/mls-state.js +56 -1
  58. package/lib/groups/store-received-grant.d.ts +4 -1
  59. package/lib/groups/store-received-grant.js +116 -1
  60. package/lib/groups/store-received-revocation.d.ts +3 -3
  61. package/lib/groups/store-received-revocation.js +82 -1
  62. package/lib/hub/ack-backoff.d.ts +22 -0
  63. package/lib/hub/ack-backoff.js +88 -0
  64. package/lib/hub/did-observing-transport.d.ts +13 -2
  65. package/lib/hub/did-observing-transport.js +126 -1
  66. package/lib/hub/errors.d.ts +4 -8
  67. package/lib/hub/errors.js +33 -1
  68. package/lib/hub/http-client.d.ts +28 -3
  69. package/lib/hub/http-client.js +32 -1
  70. package/lib/hub/hub-like.d.ts +24 -0
  71. package/lib/hub/hub-like.js +535 -0
  72. package/lib/hub/manager.d.ts +5 -4
  73. package/lib/hub/manager.js +198 -1
  74. package/lib/hub/wiring.d.ts +28 -41
  75. package/lib/hub/wiring.js +132 -1
  76. package/lib/index.d.ts +29 -13
  77. package/lib/index.js +392 -1
  78. package/lib/protocol.d.ts +8 -1
  79. package/lib/protocol.js +251 -1
  80. package/lib/schema.d.ts +2 -1
  81. package/lib/schema.js +471 -2
  82. package/lib/sync/authorize.d.ts +25 -0
  83. package/lib/sync/authorize.js +73 -0
  84. package/lib/sync/broadcast-queue.js +183 -1
  85. package/lib/sync/broadcast-sender.js +179 -1
  86. package/lib/sync/catalog-scope.js +68 -1
  87. package/lib/sync/errors.d.ts +12 -0
  88. package/lib/sync/errors.js +19 -0
  89. package/lib/sync/forwarder.js +277 -1
  90. package/lib/sync/handlers.d.ts +3 -22
  91. package/lib/sync/handlers.js +160 -1
  92. package/lib/sync/hub-tunnel-sync-listener.d.ts +9 -3
  93. package/lib/sync/hub-tunnel-sync-listener.js +172 -1
  94. package/lib/sync/hub-tunnel-sync-provider.d.ts +14 -14
  95. package/lib/sync/hub-tunnel-sync-provider.js +64 -1
  96. package/lib/sync/merkle-apply.d.ts +5 -0
  97. package/lib/sync/merkle-apply.js +194 -1
  98. package/lib/sync/merkle-channel.d.ts +19 -0
  99. package/lib/sync/merkle-channel.js +182 -1
  100. package/lib/sync/merkle-tree.js +120 -1
  101. package/lib/sync/peer-registry.d.ts +8 -1
  102. package/lib/sync/peer-registry.js +107 -1
  103. package/lib/sync/receive-access-gate.js +24 -1
  104. package/lib/sync/scope-resolver.js +41 -1
  105. package/lib/sync/sync-client.d.ts +5 -3
  106. package/lib/sync/sync-client.js +192 -1
  107. package/lib/sync/sync-manager.d.ts +2 -2
  108. package/lib/sync/sync-manager.js +272 -1
  109. package/lib/types.d.ts +41 -0
  110. package/lib/types.js +2 -1
  111. package/lib/util/mutex.js +10 -1
  112. package/lib/utils.d.ts +5 -0
  113. package/lib/utils.js +21 -0
  114. package/package.json +48 -41
  115. package/lib/groups/broadcast-service.d.ts +0 -189
  116. package/lib/groups/broadcast-service.js +0 -1
  117. package/lib/groups/wire-frame.d.ts +0 -32
  118. package/lib/groups/wire-frame.js +0 -1
  119. package/lib/hub/connection-pool.d.ts +0 -43
  120. package/lib/hub/connection-pool.js +0 -1
  121. package/lib/hub/forward-remote-broadcast.d.ts +0 -15
  122. package/lib/hub/forward-remote-broadcast.js +0 -1
  123. package/lib/hub/group-channel.d.ts +0 -67
  124. package/lib/hub/group-channel.js +0 -1
  125. package/lib/hub/hub-connection.d.ts +0 -96
  126. package/lib/hub/hub-connection.js +0 -1
  127. package/lib/hub/receive-handler.d.ts +0 -33
  128. package/lib/hub/receive-handler.js +0 -1
  129. package/lib/hub/relay-manager.d.ts +0 -127
  130. package/lib/hub/relay-manager.js +0 -1
  131. package/lib/hub/send-handler.d.ts +0 -40
  132. package/lib/hub/send-handler.js +0 -1
  133. package/lib/hub/tunnel-inbox.d.ts +0 -20
  134. package/lib/hub/tunnel-inbox.js +0 -1
  135. package/lib/hub/wait-for-gate.d.ts +0 -14
  136. package/lib/hub/wait-for-gate.js +0 -1
@@ -1 +1,130 @@
1
- import{getGraphStore as e}from"@kubun/store-graph";import{getP2PStore as t}from"@kubun/store-p2p";import{GraphQLError as r}from"graphql";export function createDelegationContext(r,u){let a=null,i=null,d=()=>a??=t(u.stores),c=()=>i??=e(u.stores);return{listOwnTokens:async({viewerDID:e,grantor:t,covers:r})=>{let n=await d(),u=Math.floor(Date.now()/1e3),a=await n.getHeldTokens({audience:e,atTime:u}),i=null!=t?a.filter(e=>e.grantor===t):a,s=i;return null!=r&&(null!=r.docID||null!=r.modelID)&&(s=await o(i,r,c)),s.map(l)},listOwnRevokedTokens:async({viewerDID:e,grantor:t})=>{let r=await d(),o=await r.getHeldRevocations({audience:e});return(null!=t?o.filter(e=>e.grantor===t):o).map(n)}}}function n(e){return{jti:e.jti,grantor:e.grantor,audience:e.audience,revokerDID:e.revoker_did,revokedAt:e.revoked_iat,verifiedAt:e.verified_at,capExp:e.cap_exp,groupID:e.group_id}}async function o(e,t,n){let o=null,l=null;if(null!=t.docID){l=t.docID;let e=await n(),u=null;try{u=await e.getDocument(t.docID)}catch{return[]}if(null==u)return[];if(o=u.model,null!=t.modelID&&t.modelID!==o)throw new r(`Document ${l} has model ${o}, not ${t.modelID}`,{extensions:{code:"DELEGATION_TOKEN_COVERS_MISMATCH"}})}else null!=t.modelID&&(o=t.modelID);if(null==o)return e;let u=new Map,a=await n(),i=u.get(o);null==i&&(i=await a.getModelInterfaces(o),u.set(o,i));let d=new Set;for(let e of(d.add(`urn:kubun:model:${o}`),i))d.add(`urn:kubun:model:${e}`);let c=null!=l?`urn:kubun:document:${l}`:null;return e.filter(e=>!!("*"===e.resource||e.resource===`urn:kubun:user:${e.grantor}`||d.has(e.resource))||null!=c&&e.resource===c)}function l(e){return{jwt:e.token,jti:e.jti,grantor:e.grantor,audience:e.audience,resource:e.resource,exp:e.exp}}
1
+ import { getDelegationStore as resolveDelegationStore } from '@kubun/store-delegation';
2
+ import { getGraphStore as resolveGraphStore } from '@kubun/store-graph';
3
+ import { getP2PStore as resolveP2PStore } from '@kubun/store-p2p';
4
+ import { GraphQLError } from 'graphql';
5
+ export function createDelegationContext(_ctx, deps) {
6
+ let p2pStorePromise = null;
7
+ let delegationStorePromise = null;
8
+ let graphStorePromise = null;
9
+ const getP2PStore = ()=>p2pStorePromise ??= resolveP2PStore(deps.stores);
10
+ const getDelegationStore = ()=>delegationStorePromise ??= resolveDelegationStore(deps.stores);
11
+ const getGraphStore = ()=>graphStorePromise ??= resolveGraphStore(deps.stores);
12
+ return {
13
+ listOwnTokens: async ({ viewerDID, grantor, covers })=>{
14
+ const delegationStore = await getDelegationStore();
15
+ const atTime = Math.floor(Date.now() / 1000);
16
+ const rows = await delegationStore.getHeldTokens({
17
+ audience: viewerDID,
18
+ atTime
19
+ });
20
+ const filteredByGrantor = grantor != null ? rows.filter((row)=>row.grantor === grantor) : rows;
21
+ let coverageFiltered = filteredByGrantor;
22
+ if (covers != null && (covers.docID != null || covers.modelID != null)) {
23
+ coverageFiltered = await applyCoverageFilter(filteredByGrantor, covers, getGraphStore);
24
+ }
25
+ return coverageFiltered.map(rowToData);
26
+ },
27
+ listOwnRevokedTokens: async ({ viewerDID, grantor })=>{
28
+ const [delegationStore, p2pStore] = await Promise.all([
29
+ getDelegationStore(),
30
+ getP2PStore()
31
+ ]);
32
+ const rows = await delegationStore.getHeldRevocations({
33
+ audience: viewerDID
34
+ });
35
+ const filtered = grantor != null ? rows.filter((row)=>row.grantor === grantor) : rows;
36
+ // The core revocation row carries no group; enrich each with the group the
37
+ // cap was granted in via the p2p `jti` edge. A held revocation always has
38
+ // a locally-held cap, and every locally-stored cap wrote an edge at grant
39
+ // time, so the lookup resolves; a row with no edge is dropped rather than
40
+ // reported with an unknown group.
41
+ const jtis = filtered.map((row)=>row.jti);
42
+ const groupByJTI = await p2pStore.getGroupIDsByJTIs(jtis);
43
+ const enriched = filtered.map((row)=>{
44
+ const groupID = groupByJTI.get(row.jti);
45
+ return groupID != null ? revocationRowToData(row, groupID) : null;
46
+ });
47
+ return enriched.filter((data)=>data != null);
48
+ }
49
+ };
50
+ }
51
+ function revocationRowToData(row, groupID) {
52
+ return {
53
+ jti: row.jti,
54
+ grantor: row.grantor,
55
+ audience: row.audience,
56
+ revokerDID: row.revoker_did,
57
+ revokedAt: row.revoked_iat,
58
+ verifiedAt: row.verified_at,
59
+ capExp: row.cap_exp,
60
+ groupID
61
+ };
62
+ }
63
+ async function applyCoverageFilter(rows, covers, getGraphStore) {
64
+ // Resolve concrete model. When `docID` is supplied it wins (its derived model
65
+ // is authoritative); when both are supplied, the doc's model must match the
66
+ // hint or the caller's intent is ambiguous — reject with an explicit error.
67
+ let modelID = null;
68
+ let docID = null;
69
+ if (covers.docID != null) {
70
+ docID = covers.docID;
71
+ const graphStore = await getGraphStore();
72
+ // A malformed docID — one the document store cannot parse — is treated the
73
+ // same as a doc that does not exist locally: no token can cover it, so
74
+ // the result is empty.
75
+ let doc = null;
76
+ try {
77
+ doc = await graphStore.getDocument(covers.docID);
78
+ } catch {
79
+ return [];
80
+ }
81
+ if (doc == null) {
82
+ return [];
83
+ }
84
+ modelID = doc.model;
85
+ if (covers.modelID != null && covers.modelID !== modelID) {
86
+ throw new GraphQLError(`Document ${docID} has model ${modelID}, not ${covers.modelID}`, {
87
+ extensions: {
88
+ code: 'DELEGATION_TOKEN_COVERS_MISMATCH'
89
+ }
90
+ });
91
+ }
92
+ } else if (covers.modelID != null) {
93
+ modelID = covers.modelID;
94
+ }
95
+ if (modelID == null) {
96
+ return rows;
97
+ }
98
+ // Per-call interface cache. Single model in this resolver call, but the
99
+ // cache keeps the shape consistent if the API grows multi-model later.
100
+ const interfaceCache = new Map();
101
+ const graphStore = await getGraphStore();
102
+ let interfaceIDs = interfaceCache.get(modelID);
103
+ if (interfaceIDs == null) {
104
+ interfaceIDs = await graphStore.getModelInterfaces(modelID);
105
+ interfaceCache.set(modelID, interfaceIDs);
106
+ }
107
+ const modelResources = new Set();
108
+ modelResources.add(`urn:kubun:model:${modelID}`);
109
+ for (const id of interfaceIDs){
110
+ modelResources.add(`urn:kubun:model:${id}`);
111
+ }
112
+ const docResource = docID != null ? `urn:kubun:document:${docID}` : null;
113
+ return rows.filter((row)=>{
114
+ if (row.resource === '*') return true;
115
+ if (row.resource === `urn:kubun:user:${row.grantor}`) return true;
116
+ if (modelResources.has(row.resource)) return true;
117
+ if (docResource != null && row.resource === docResource) return true;
118
+ return false;
119
+ });
120
+ }
121
+ function rowToData(row) {
122
+ return {
123
+ jwt: row.token,
124
+ jti: row.jti,
125
+ grantor: row.grantor,
126
+ audience: row.audience,
127
+ resource: row.resource,
128
+ exp: row.exp
129
+ };
130
+ }