@ibgib/core-gib 0.1.22 → 0.1.25

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 (86) hide show
  1. package/dist/common/other/graph-helper.d.mts +25 -0
  2. package/dist/common/other/graph-helper.d.mts.map +1 -1
  3. package/dist/common/other/graph-helper.mjs +75 -1
  4. package/dist/common/other/graph-helper.mjs.map +1 -1
  5. package/dist/sync/graft-info/graft-info-helpers.mjs +2 -2
  6. package/dist/sync/graft-info/graft-info-helpers.mjs.map +1 -1
  7. package/dist/sync/sync-conflict.respec.mjs +8 -12
  8. package/dist/sync/sync-conflict.respec.mjs.map +1 -1
  9. package/dist/sync/sync-constants.d.mts +14 -4
  10. package/dist/sync/sync-constants.d.mts.map +1 -1
  11. package/dist/sync/sync-constants.mjs +15 -3
  12. package/dist/sync/sync-constants.mjs.map +1 -1
  13. package/dist/sync/sync-helpers.d.mts +22 -15
  14. package/dist/sync/sync-helpers.d.mts.map +1 -1
  15. package/dist/sync/sync-helpers.mjs +159 -90
  16. package/dist/sync/sync-helpers.mjs.map +1 -1
  17. package/dist/sync/sync-innerspace-constants.respec.mjs +8 -9
  18. package/dist/sync/sync-innerspace-constants.respec.mjs.map +1 -1
  19. package/dist/sync/sync-innerspace-deep-updates.respec.mjs +8 -9
  20. package/dist/sync/sync-innerspace-deep-updates.respec.mjs.map +1 -1
  21. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs +8 -9
  22. package/dist/sync/sync-innerspace-dest-ahead.respec.mjs.map +1 -1
  23. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs +8 -9
  24. package/dist/sync/sync-innerspace-multiple-timelines.respec.mjs.map +1 -1
  25. package/dist/sync/sync-innerspace-partial-update.respec.mjs +8 -9
  26. package/dist/sync/sync-innerspace-partial-update.respec.mjs.map +1 -1
  27. package/dist/sync/sync-innerspace.respec.mjs +6 -7
  28. package/dist/sync/sync-innerspace.respec.mjs.map +1 -1
  29. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.d.mts +2 -0
  30. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.d.mts.map +1 -1
  31. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs +4 -0
  32. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mjs.map +1 -1
  33. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-types.d.mts +0 -15
  34. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-types.d.mts.map +1 -1
  35. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts +30 -16
  36. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
  37. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +47 -79
  38. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
  39. package/dist/sync/sync-peer/sync-peer-types.d.mts +40 -1
  40. package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
  41. package/dist/sync/sync-peer/sync-peer-v1.d.mts +47 -14
  42. package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
  43. package/dist/sync/sync-peer/sync-peer-v1.mjs +188 -144
  44. package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
  45. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts +39 -3
  46. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
  47. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +137 -31
  48. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
  49. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +5 -0
  50. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
  51. package/dist/sync/sync-saga-coordinator.d.mts +81 -77
  52. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  53. package/dist/sync/sync-saga-coordinator.mjs +608 -597
  54. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  55. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +154 -26
  56. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
  57. package/dist/sync/sync-types.d.mts +87 -92
  58. package/dist/sync/sync-types.d.mts.map +1 -1
  59. package/dist/sync/sync-types.mjs +6 -2
  60. package/dist/sync/sync-types.mjs.map +1 -1
  61. package/dist/timeline/timeline-api.d.mts.map +1 -1
  62. package/dist/timeline/timeline-api.mjs +15 -8
  63. package/dist/timeline/timeline-api.mjs.map +1 -1
  64. package/package.json +1 -1
  65. package/src/common/other/graph-helper.mts +79 -1
  66. package/src/sync/graft-info/graft-info-helpers.mts +3 -3
  67. package/src/sync/sync-conflict.respec.mts +8 -14
  68. package/src/sync/sync-constants.mts +15 -4
  69. package/src/sync/sync-helpers.mts +173 -101
  70. package/src/sync/sync-innerspace-constants.respec.mts +8 -9
  71. package/src/sync/sync-innerspace-deep-updates.respec.mts +8 -9
  72. package/src/sync/sync-innerspace-dest-ahead.respec.mts +8 -9
  73. package/src/sync/sync-innerspace-multiple-timelines.respec.mts +8 -9
  74. package/src/sync/sync-innerspace-partial-update.respec.mts +9 -12
  75. package/src/sync/sync-innerspace.respec.mts +6 -7
  76. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-constants.mts +7 -0
  77. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-types.mts +0 -15
  78. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +72 -96
  79. package/src/sync/sync-peer/sync-peer-types.mts +43 -2
  80. package/src/sync/sync-peer/sync-peer-v1.mts +215 -142
  81. package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +145 -37
  82. package/src/sync/sync-saga-context/sync-saga-context-types.mts +5 -0
  83. package/src/sync/sync-saga-coordinator.mts +680 -714
  84. package/src/sync/sync-saga-message/sync-saga-message-types.mts +160 -24
  85. package/src/sync/sync-types.mts +96 -105
  86. package/src/timeline/timeline-api.mts +17 -10
@@ -1,18 +1,25 @@
1
1
  /**
2
- * @module SyncPeer_V1 witness class
2
+ * @module SyncPeer_V1 witness class for base class plumbing of sync peers.
3
+ *
4
+ * You are expected to implement concrete peer classes for concrete architecture.
3
5
  */
4
6
 
5
7
  import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
6
8
  import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
7
9
  import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
8
- import { SubjectWitness } from '../../common/pubsub/subject/subject-types.mjs';
10
+ import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
11
+ import { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
9
12
 
10
13
  import { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
11
14
  import { SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN } from '../sync-constants.mjs';
15
+ import { SubjectWitness } from '../../common/pubsub/subject/subject-types.mjs';
12
16
  import { SyncSagaContextIbGib_V1 } from '../sync-saga-context/sync-saga-context-types.mjs';
13
- import { SyncPeerData_V1, SyncPeerRel8ns_V1, SyncPeerWitness } from './sync-peer-types.mjs';
17
+ import { InitializeSyncPeerOpts, SyncPeerData_V1, SyncPeerRel8ns_V1, SyncPeerWitness } from './sync-peer-types.mjs';
14
18
  import { LightWitnessBase_V1 } from '../../witness/light-witness-base-v1.mjs';
15
- import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
19
+ import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
20
+ import { newupSubject } from '../../common/pubsub/subject/subject-helper.mjs';
21
+ import { validateContextAndSagaFrame } from '../sync-saga-context/sync-saga-context-helpers.mjs';
22
+ import { getFromSpace } from '../../witness/space/space-helper.mjs';
16
23
 
17
24
  const logalot = GLOBAL_LOG_A_LOT || true;
18
25
  const logalotControlDomain = true;
@@ -20,20 +27,22 @@ const lcControlDomain = '[ControlDomain]';
20
27
 
21
28
  /**
22
29
  * Abstract witness for talking to a Sync Peer (e.g. Remote Node or Local Simulator).
23
- *
30
+ *
24
31
  * Takes a SyncSagaContext (Request) and returns a SyncSagaContext (Response).
25
- *
32
+ *
26
33
  * Implements the core "Sync Protocol Transport" logic:
27
34
  * 1. Push Context & Dependencies (Sender -> Receiver)
28
35
  * 2. Send Request (RPC)
29
36
  * 3. Pull Response & Dependencies (Receiver -> Sender)
30
37
  */
31
- export abstract class SyncPeer_V1 extends LightWitnessBase_V1<SyncPeerData_V1, SyncPeerRel8ns_V1>
32
- implements SyncPeerWitness {
38
+ export abstract class SyncPeer_V1<TInitializeOpts extends InitializeSyncPeerOpts = InitializeSyncPeerOpts>
39
+ extends LightWitnessBase_V1<SyncPeerData_V1, SyncPeerRel8ns_V1>
40
+ implements SyncPeerWitness<TInitializeOpts> {
33
41
 
34
42
  protected lc: string = `[${SyncPeer_V1.name}]`;
35
43
 
36
- abstract payloadIbGibsDomainReceived$: SubjectWitness<IbGib_V1>;
44
+ public opts: TInitializeOpts | undefined;
45
+ public payloadIbGibsDomainReceived$!: SubjectWitness<IbGib_V1>;
37
46
 
38
47
  get classname(): string {
39
48
  if (!this.data) { throw new Error(`(UNEXPECTED) this.data falsy? (E: 1ab1841e9338b54f3aa615fa37024826)`); }
@@ -44,32 +53,156 @@ export abstract class SyncPeer_V1 extends LightWitnessBase_V1<SyncPeerData_V1, S
44
53
  constructor(initialData: SyncPeerData_V1, initialRel8ns?: SyncPeerRel8ns_V1) {
45
54
  super(initialData, initialRel8ns);
46
55
  }
56
+
57
+ public async initialize(): Promise<void> {
58
+ this.payloadIbGibsDomainReceived$ = await newupSubject<IbGib_V1>();
59
+ }
60
+
61
+ /**
62
+ * base implementation just sets the opts property.
63
+ *
64
+ * override this in concrete classes for further initialization code
65
+ * specific to the sender.
66
+ *
67
+ * @see {@link SyncPeerWitness.opts}
68
+ */
69
+ public async initializeSender(opts: TInitializeOpts): Promise<void> {
70
+ const lc = `${this.lc}[${this.initializeSender.name}]`;
71
+ try {
72
+ if (logalot) { console.log(`${lc} starting... (I: 31bd5fda37c89fa37fbaf14daf5fe726)`); }
73
+ this.opts = opts;
74
+ } catch (error) {
75
+ console.error(`${lc} ${extractErrorMsg(error)}`);
76
+ throw error;
77
+ } finally {
78
+ if (logalot) { console.log(`${lc} complete.`); }
79
+ }
80
+ }
81
+
82
+ public setOptionalOpts(arg: Partial<TInitializeOpts>): void {
83
+ const lc = `${this.lc}[${this.setOptionalOpts.name}]`;
84
+ try {
85
+ if (logalot) { console.log(`${lc} starting... (I: ae5ddbd3577db267f84743175a736626)`); }
86
+ if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? (E: 0dd4d6080a6e2f31d86cf4d86e11b826)`); }
87
+
88
+ if (logalot) { console.log(`${lc} updating opts. arg keys: ${Object.keys(arg)} (I: 452d78a558f8fc3468c8e2e68c70b226)`); }
89
+
90
+ this.opts = { ...this.opts, ...arg };
91
+ } catch (error) {
92
+ console.error(`${lc} ${extractErrorMsg(error)}`);
93
+ throw error;
94
+ } finally {
95
+ if (logalot) { console.log(`${lc} complete.`); }
96
+ }
97
+ }
98
+
99
+ // public setOptionalOpts({
100
+ // senderTempSpace,
101
+ // }: {
102
+ // senderTempSpace: IbGibSpaceAny,
103
+ // }): void {
104
+ // const lc = `${this.lc}[${this.setOptionalOpts.name}]`;
105
+ // try {
106
+ // if (logalot) { console.log(`${lc} starting... (I: a17188953e38f07b1884e498ac490b26)`); }
107
+ // if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? (E: bdf00fe4b89b07ea78860d6ebe922e26)`); }
108
+
109
+ // this.opts.senderTempSpace = senderTempSpace;
110
+ // } catch (error) {
111
+ // console.error(`${lc} ${extractErrorMsg(error)}`);
112
+ // throw error;
113
+ // } finally {
114
+ // if (logalot) { console.log(`${lc} complete.`); }
115
+ // }
116
+ // }
117
+
118
+ protected abstract ensureReceiverTempSpace(): Promise<IbGibSpaceAny>;
119
+
47
120
  /**
48
121
  * Witness the synchronization context (Send/Receive).
49
- *
122
+ *
123
+ * At this point in code, we are sending the context OUTGOING. The {@link context} should
124
+ * have a fully populated {@link SyncSagaContextIbGib_V1.sagaFrame}
125
+ *
50
126
  * @param arg The OUTGOING context (Request).
51
127
  * @returns The INCOMING context (Response), or undefined if failed/empty.
52
128
  */
53
- async witness(arg: SyncSagaContextIbGib_V1): Promise<SyncSagaContextIbGib_V1 | undefined> {
129
+ override async witness(context: SyncSagaContextIbGib_V1): Promise<SyncSagaContextIbGib_V1 | undefined> {
54
130
  const lc = `${this.lc}[${this.witness.name}]`;
55
131
  try {
56
132
  if (logalot) { console.log(`${lc} starting...`); }
57
133
 
58
- if (logalot) { console.log(`${lc} starting...`); }
134
+ if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? Concrete class should have initialized sender opts by now. (E: 0b9e28287318fdf8bf9f5a6886a24826)`); }
135
+
136
+ // NOTE: There are two basic types of peers:
137
+ // * local-only (peer)
138
+ // * this peer is both sender/receiver peer
139
+ // * for local merges and relatively fast spaces
140
+ // * proxy to remote space
141
+ // * this peer is both sender/receiver peer
142
+ // * works directly with remote/outerspaces
143
+ // * Less efficient over-the-wire xfer due to chatiness
144
+ // * symmetric node sender/receiver peers
145
+ // * separate sender/receiver classes
146
+ // * e.g., SyncPeerClient[Substrate]Sender_V1,
147
+ // SyncPeerClient[Substrate]Receiver_V1
148
+ // * More efficient over-the-wire xfer
149
+ // * Most difficult to mentally model
150
+ // * sender.witness does the pushing out
151
+ // * what the sender/initiator's coordinator has a reference to
152
+ // * receiver.witness does the coming in
153
+ // * lives on a server/remote instance with its own coordinator
154
+ // instance
155
+ // * must do its own validation/authn/authz for possible MITM
156
+ // issues
157
+ // The following is a sketch where some of these may be blurred
158
+
159
+ // persist the context, sagaframe, identity(s) ONLY in the receiver's durable space
160
+ // if sending domain ibgibs...
161
+ // verify the domain ibgibs intrinsically.
162
+ // persist the domain ibgibs in the receiver's temp space (push all addrs?)
163
+ // await until all domain ibgibs are in receiver's temp space
164
+ // process the context with the receiver's coordinator to get a new response context
165
+ // analyze the response context
166
+ // validate context intrinsically
167
+ // validate return identity if present
168
+ // persist the response context's dependency graph (context, saga frame and msg(s), identities)
169
+ // if response has payload domain ibgibs,
170
+ // spin off...
171
+ // pull domain ibgibs to local temp space
172
+ // publish domain ibgibs to observable
173
+ // when all domain ibgibs are pulled, publish complete to the observable
174
+ // return resulting context ibgib (which the caller should get BEFORE the domain ibgibs observable completes)
175
+
176
+ // validate, authenticate, and authorize the context, sagaFrame, and identity(s)
177
+ const validationErrors = await validateContextAndSagaFrame({ context });
178
+ if (validationErrors.length > 0) {
179
+ throw new Error(`invalid context received. validationErrors: ${validationErrors} (E: 8b34c875c968af29bc433138e57a7826)`);
180
+ }
181
+ const authenticationErrors = await this.authenticateContext({ context });
182
+ if (authenticationErrors.length > 0) {
183
+ throw new Error(`invalid context authentication. authenticationErrors: ${authenticationErrors} (E: da89da5ee1269aeb78952d475d607526)`);
184
+ }
185
+ const authorizationErrors = await this.authorizeContext({ context });
186
+ if (authorizationErrors.length > 0) {
187
+ throw new Error(`invalid context authorization. authorizationErrors: ${authorizationErrors} (E: 8ddc284a758cf10ba829334c1babb826)`);
188
+ }
59
189
 
60
- // 1. PUSH: Ensure Request Data is available on Receiver
61
- await this.pushContextGraph({ context: arg });
190
+ // at this point, we have a valid, authenticated, authorized context
62
191
 
63
192
  // 2. EXECUTE: Trigger Remote Processing
64
- const response = await this.sendContextRequest(arg);
193
+ const response = await this.sendContextRequest(context);
65
194
 
66
195
  if (!response) {
67
196
  if (logalot) { console.log(`${lc} No response from peer.`); }
68
197
  return undefined;
69
198
  }
70
199
 
71
- // 3. PULL: Ensure Response Data is available on Sender (Local)
72
- await this.pullContextGraph({ context: response });
200
+ // at this point, all outgoing payload domain ibgibs have been sent.
201
+ // we have received the response context, wherein the sync saga
202
+ // frame/msg stone(s) and any keystones should be evolved. Depending
203
+ // on the concrete implementation, if there are domain ibgibs to
204
+ // receive, they may still be transferring. These will be published
205
+ // to this.payloadIbGibsDomainReceived$
73
206
 
74
207
  return response;
75
208
 
@@ -82,13 +215,25 @@ export abstract class SyncPeer_V1 extends LightWitnessBase_V1<SyncPeerData_V1, S
82
215
  }
83
216
 
84
217
  /**
85
- * Transmits the Context IbGib itself to the Peer.
218
+ * This is responsible for:
219
+ *
220
+ * * sending outgoing {@link context}, the sync saga frame and msg stone(s),
221
+ * and identities...
222
+ * * AND sending OUTGOING domain ibgibs
223
+ * {@link SyncSagaContextIbGib_V1.payloadIbGibsDomain}
224
+ * * getting back the other end's resultant context ibgib, sync saga frame
225
+ * and msg stone(s), and identities in their entirety...
226
+ * * AND stream/receiving the RESPONSE payload domain ibgibs, publishing
227
+ * these to this.payloadIbGibsDomainReceived$.
228
+ *
229
+ * So this returns the RESPONSE context, possibly BEFORE the RESPONSE domain
230
+ * ibgibs have been completely received/streamed. The coordinator is responsible
86
231
  */
87
232
  protected abstract sendContextRequest(context: SyncSagaContextIbGib_V1): Promise<SyncSagaContextIbGib_V1 | undefined>;
88
233
 
89
234
  /**
90
235
  * Pushes specific IbGib(s) (by address) from Local to Remote.
91
- *
236
+ *
92
237
  * Should NOT have to handle identifying if the remote already has it
93
238
  * (optimization), because the sync coordinator should be doing this in
94
239
  * its diffing algorithm.
@@ -100,145 +245,73 @@ export abstract class SyncPeer_V1 extends LightWitnessBase_V1<SyncPeerData_V1, S
100
245
  */
101
246
  protected abstract pull(addrs: IbGibAddr[]): Promise<void>;
102
247
 
248
+
249
+
103
250
  /**
104
- * Helper to orchestrate the PUSH of a Context's dependency graph.
251
+ * move to sync-peer-helpers.mts as a pure function?
105
252
  */
106
- protected async pushContextGraph({ context }: { context: SyncSagaContextIbGib_V1 }): Promise<void> {
107
- const lc = `[${SyncPeer_V1.name}][pushContextGraph]`;
108
-
109
- // A. Push Context Envelope
110
- const contextAddr = getIbGibAddr({ ibGib: context });
111
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH Context Envelope -> ${contextAddr} (I: 3f4e5a6b7c8d9e0f)`); }
112
- await this.push([contextAddr]);
113
-
114
- // B. Push Saga Frame & Immediate Deps (Msg, Identity)
115
- const frameAddr = context.rel8ns?.sagaFrame?.[0];
116
- if (frameAddr) {
117
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH CONTROL: Saga Frame -> ${frameAddr} (I: 4a5b6c7d8e9f0a1b)`); }
118
- await this.push([frameAddr]);
119
- // We inspect the local frame to find its immediate deps
120
- const frame = await this.getLocalIbGib(frameAddr);
121
- if (frame) {
122
- // Msg Stone
123
- const msgAddrs = frame.rel8ns?.[SYNC_MSG_REL8N_NAME];
124
- if (msgAddrs) {
125
- for (const addr of msgAddrs) {
126
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH CONTROL: Msg Stone -> ${addr} (I: 5b6c7d8e9f0a1b2c)`); }
127
- await this.push([addr]);
128
- }
129
- }
130
- // Identity
131
- const idAddrs = frame.rel8ns?.identity;
132
- if (idAddrs) {
133
- for (const addr of idAddrs) {
134
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH CONTROL: Identity -> ${addr} (I: 6c7d8e9f0a1b2c3d)`); }
135
- await this.push([addr]);
136
- }
137
- }
138
- }
139
- }
253
+ protected async authenticateContext({ context }: { context: SyncSagaContextIbGib_V1 }): Promise<string[]> {
254
+ const lc = `${this.lc}[${this.authenticateContext.name}]`;
255
+ try {
256
+ if (logalot) { console.log(`${lc} starting... (I: 2677a482dfa873dcd1aa04a3031ff826)`); }
140
257
 
141
- // C. Push Session Identity
142
- const sessionKeystoneAddr = context.rel8ns?.sessionKeystone?.[0];
143
- if (sessionKeystoneAddr) {
144
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH CONTROL: Session Keystone -> ${sessionKeystoneAddr} (I: 7d8e9f0a1b2c3d4e)`); }
145
- await this.push([sessionKeystoneAddr]);
146
- }
258
+ console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. // todo: authenticate (v1 must have this after we get merge logic workflow going) (E: bc3a78f2dab18ab64c36d055a4b50526)`);
147
259
 
148
- // D. Push Payloads (Deep/Soft)
149
- // For payloads, the Peer is just a transport. It doesn't know the structure.
150
- // It relies on "push" handling the "deep" transfer if needed, or we explicitly iterate if we had a graph.
151
- // But since we are "Witnessing", we usually assume "push(addr)" acts like "copy(addr, recursive=true)"?
152
- // Or do we need to be explicit?
153
- // User said: "payloads should be flat... sync coordinator is the one doing the heavy lifting".
154
- // So we just push the addrs listed.
155
-
156
- // 1. Control Payloads
157
- // const controlAddrs = context.data?.[SYNC_SAGA_PAYLOAD_ADDRS_CONTROL];
158
- // if (controlAddrs && controlAddrs.length > 0) {
159
- // if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH CONTROL PAYLOADS (${controlAddrs.length}): ${controlAddrs.join(', ')} (I: 8e9f0a1b2c3d4e5f)`); }
160
- // for (const addr of controlAddrs) {
161
- // await this.push(addr);
162
- // }
163
- // }
164
-
165
- // 2. Domain Payloads
166
- const domainAddrs = context.data?.[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN];
167
- if (domainAddrs && domainAddrs.length > 0) {
168
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH DOMAIN PAYLOADS (${domainAddrs.length}): ${domainAddrs.join(', ')} (I: 9f0a1b2c3d4e5f6a)`); }
169
- for (const addr of domainAddrs) {
170
- await this.push([addr]);
171
- }
260
+ return [];
261
+ } catch (error) {
262
+ console.error(`${lc} ${extractErrorMsg(error)}`);
263
+ throw error;
264
+ } finally {
265
+ if (logalot) { console.log(`${lc} complete.`); }
172
266
  }
173
-
174
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PUSH COMPLETE for context ${contextAddr} (I: a0b1c2d3e4f5a6b7)`); }
175
267
  }
176
268
 
177
269
  /**
178
- * Helper to orchestrate the PULL of a Context's dependency graph.
270
+ * move to sync-peer-helpers.mts as a pure function?
179
271
  */
180
- protected async pullContextGraph({ context }: { context: SyncSagaContextIbGib_V1 }): Promise<void> {
181
- const lc = `[${SyncPeer_V1.name}][pullContextGraph]`;
182
-
183
- // A. Pull Context Envelope
184
- const contextAddr = getIbGibAddr({ ibGib: context });
185
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL Context Envelope <- ${contextAddr} (I: b1c2d3e4f5a6b7c8)`); }
186
- await this.pull([contextAddr]);
187
-
188
- // B. Pull Saga Frame & Immediate Deps
189
- const frameAddr = context.rel8ns?.sagaFrame?.[0];
190
- if (frameAddr) {
191
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL CONTROL: Saga Frame <- ${frameAddr} (I: c2d3e4f5a6b7c8d9)`); }
192
- await this.pull([frameAddr]);
193
- // Inspect REMOTE frame? We need to have pulled it first.
194
- const frame = await this.getLocalIbGib(frameAddr); // Should be local now
195
- if (frame) {
196
- const msgAddrs = frame.rel8ns?.[SYNC_MSG_REL8N_NAME];
197
- if (msgAddrs) {
198
- for (const addr of msgAddrs) {
199
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL CONTROL: Msg Stone <- ${addr} (I: d3e4f5a6b7c8d9e0)`); }
200
- await this.pull([addr]);
201
- }
202
- }
203
- const idAddrs = frame.rel8ns?.identity;
204
- if (idAddrs) {
205
- for (const addr of idAddrs) {
206
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL CONTROL: Identity <- ${addr} (I: e4f5a6b7c8d9e0f1)`); }
207
- await this.pull([addr]);
208
- }
209
- }
210
- }
211
- }
272
+ protected async authorizeContext({ context }: { context: SyncSagaContextIbGib_V1 }): Promise<string[]> {
273
+ const lc = `${this.lc}[${this.authorizeContext.name}]`;
274
+ try {
275
+ if (logalot) { console.log(`${lc} starting... (I: 48c918b41ceec0cd489ca3b8819e6826)`); }
212
276
 
213
- // C. Pull Session Identity
214
- const sessionKeystoneAddr = context.rel8ns?.sessionKeystone?.[0];
215
- if (sessionKeystoneAddr) {
216
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL CONTROL: Session Keystone <- ${sessionKeystoneAddr} (I: f5a6b7c8d9e0f1a2)`); }
217
- await this.pull([sessionKeystoneAddr]);
218
- }
277
+ console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. authorize business logic (v1 must have this, but later when we are working on admin vs. student)(E: bc3a78f2dab18ab64c36d055a4b50526)`);
219
278
 
220
- // D. Pull Payloads
221
- // const controlAddrs = context.data?.[SYNC_SAGA_PAYLOAD_ADDRS_CONTROL];
222
- // if (controlAddrs && controlAddrs.length > 0) {
223
- // if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL CONTROL PAYLOADS (${controlAddrs.length}): ${controlAddrs.join(', ')} (I: a6b7c8d9e0f1a2b3)`); }
224
- // for (const addr of controlAddrs) {
225
- // await this.pull(addr);
226
- // }
227
- // }
228
- const domainAddrs = context.data?.[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN];
229
- if (domainAddrs && domainAddrs.length > 0) {
230
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL DOMAIN PAYLOADS (${domainAddrs.length}): ${domainAddrs.join(', ')} (I: b7c8d9e0f1a2b3c4)`); }
231
- for (const addr of domainAddrs) {
232
- await this.pull([addr]);
233
- }
279
+ return [];
280
+ } catch (error) {
281
+ console.error(`${lc} ${extractErrorMsg(error)}`);
282
+ throw error;
283
+ } finally {
284
+ if (logalot) { console.log(`${lc} complete.`); }
234
285
  }
235
-
236
- if (logalotControlDomain) { console.log(`${lc}${lcControlDomain} PULL COMPLETE for context ${contextAddr} (I: c8d9e0f1a2b3c4d5)`); }
237
286
  }
238
287
 
239
288
  /**
240
289
  * Abstract accessor to get an IbGib from the Local space/store.
241
290
  * Needed for inspecting rela8ns during the graph walk.
291
+ *
292
+ * Default implementation simply looks in senderSpace
242
293
  */
243
- protected abstract getLocalIbGib(addr: string): Promise<IbGib_V1 | undefined>;
294
+ protected async getLocalIbGib(addr: string): Promise<IbGib_V1 | undefined> {
295
+ const lc = `${this.lc}[${this.getLocalIbGib.name}]`;
296
+ try {
297
+ if (logalot) { console.log(`${lc} starting... (I: 27b248cb9801eeb2386b71485389a826)`); }
298
+
299
+ console.warn(`${lc} possibly a bottleneck here, getLocalIbGib only gets a single ibgib... (W: 2fd448a435480e6b128f6b8bcbef4826)`);
300
+ if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? (E: cfb9431f2fb851f24a6c88e80c3b3326)`); }
301
+
302
+ const resGet = await getFromSpace({ space: this.opts.senderSpace, addr });
303
+
304
+ if (resGet.success && resGet.ibGibs && resGet.ibGibs.length === 1) {
305
+ const ibGib = resGet.ibGibs[0];
306
+ return ibGib;
307
+ } else {
308
+ throw new Error(`couldn't get addr (${addr}) from local space ${this.opts.senderSpace}. reason: ${resGet.errorMsg ?? 'unknown error (E: 926ef8bf4fcc299ab89dba34ea691a26)'} (E: d8a89807e471d3f8b938ab21df44cb26)`);
309
+ }
310
+ } catch (error) {
311
+ console.error(`${lc} ${extractErrorMsg(error)}`);
312
+ throw error;
313
+ } finally {
314
+ if (logalot) { console.log(`${lc} complete.`); }
315
+ }
316
+ }
244
317
  }