@novasamatech/host-papp 0.7.9-5 → 0.7.9

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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Lightweight public entry for the debug bus. Lives outside the main
3
+ * `index.ts` so consumers can import the debug surface without
4
+ * loading the attestation / session-manager modules, which pull in
5
+ * verifiablejs WASM that can't initialise in all environments.
6
+ */
7
+ export { emitHostPappDebugMessage, hasHostPappDebugListeners, onHostPappDebugMessage } from './debugBus.js';
8
+ export type { AttestationDebugEvent, HostPappDebugEvent, SessionDebugEvent, SsoDebugEvent } from './debugTypes.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Lightweight public entry for the debug bus. Lives outside the main
3
+ * `index.ts` so consumers can import the debug surface without
4
+ * loading the attestation / session-manager modules, which pull in
5
+ * verifiablejs WASM that can't initialise in all environments.
6
+ */
7
+ export { emitHostPappDebugMessage, hasHostPappDebugListeners, onHostPappDebugMessage } from './debugBus.js';
@@ -0,0 +1,20 @@
1
+ import type { HostPappDebugEvent } from './debugTypes.js';
2
+ /** @internal For host-papp emitters. */
3
+ export declare function emitHostPappDebugMessage(event: HostPappDebugEvent): void;
4
+ /**
5
+ * @internal Lets call sites skip non-trivial payload construction
6
+ * when nobody is listening. Equivalent in spirit to the lazy
7
+ * subscribe pattern in host-api's transport-level hook.
8
+ */
9
+ export declare function hasHostPappDebugListeners(): boolean;
10
+ /**
11
+ * EXPERIMENTAL. Subscribe to every host-papp debug event across all
12
+ * adapters in the current process. Returns an unsubscribe function.
13
+ *
14
+ * Each listener is isolated: a throw inside one callback is logged
15
+ * to `console.error` and does not starve sibling subscribers — the
16
+ * same pattern host-api uses in its transport-level debug hook.
17
+ */
18
+ export declare function onHostPappDebugMessage(callback: (event: HostPappDebugEvent) => void): VoidFunction;
19
+ /** @internal Convenience for creating flow identifiers. */
20
+ export declare function createFlowId(): string;
@@ -0,0 +1,61 @@
1
+ import { createNanoEvents } from 'nanoevents';
2
+ import { nanoid } from 'nanoid';
3
+ /**
4
+ * EXPERIMENTAL. Module-level bus that aggregates debug events from
5
+ * every host-papp adapter created in this process. Mirrors the
6
+ * pattern used by `onHostApiDebugMessage` in
7
+ * `@novasamatech/host-container` so a single subscriber can observe
8
+ * pairing / attestation / session activity alongside TrUAPI traffic.
9
+ *
10
+ * Subscription is *lazy in spirit*: emit sites should call
11
+ * `hasHostPappDebugListeners()` before constructing payloads that
12
+ * are non-trivial to compute.
13
+ */
14
+ const bus = createNanoEvents();
15
+ let listenerCount = 0;
16
+ /** @internal For host-papp emitters. */
17
+ export function emitHostPappDebugMessage(event) {
18
+ if (listenerCount === 0)
19
+ return;
20
+ bus.emit('message', event);
21
+ }
22
+ /**
23
+ * @internal Lets call sites skip non-trivial payload construction
24
+ * when nobody is listening. Equivalent in spirit to the lazy
25
+ * subscribe pattern in host-api's transport-level hook.
26
+ */
27
+ export function hasHostPappDebugListeners() {
28
+ return listenerCount > 0;
29
+ }
30
+ /**
31
+ * EXPERIMENTAL. Subscribe to every host-papp debug event across all
32
+ * adapters in the current process. Returns an unsubscribe function.
33
+ *
34
+ * Each listener is isolated: a throw inside one callback is logged
35
+ * to `console.error` and does not starve sibling subscribers — the
36
+ * same pattern host-api uses in its transport-level debug hook.
37
+ */
38
+ export function onHostPappDebugMessage(callback) {
39
+ listenerCount++;
40
+ const safeCallback = (event) => {
41
+ try {
42
+ callback(event);
43
+ }
44
+ catch (e) {
45
+ console.error('host-papp debug listener threw', e);
46
+ }
47
+ };
48
+ const unsubscribe = bus.on('message', safeCallback);
49
+ let disposed = false;
50
+ return () => {
51
+ if (disposed)
52
+ return;
53
+ disposed = true;
54
+ listenerCount = Math.max(0, listenerCount - 1);
55
+ unsubscribe();
56
+ };
57
+ }
58
+ /** @internal Convenience for creating flow identifiers. */
59
+ export function createFlowId() {
60
+ return nanoid();
61
+ }
@@ -0,0 +1,204 @@
1
+ /**
2
+ * EXPERIMENTAL. Discriminated union of every host-papp debug event.
3
+ * The taxonomy is split into three "layers": SSO pairing, guest
4
+ * identity attestation, and post-pairing session activity. Every
5
+ * variant carries `{ layer, event, flowId, timestamp, payload }`.
6
+ *
7
+ * `flowId` correlates steps that belong to the same logical flow
8
+ * (e.g. one full pairing dance shares a flowId across all of its
9
+ * steps). Conventions per layer:
10
+ * - `sso.*` and `attestation.*`: one fresh flowId per pairing /
11
+ * attestation attempt, shared across all of its steps.
12
+ * - `session.opened` / `session.terminated`: reuse `sessionId` as the
13
+ * flowId so that a `(opened, terminated)` pair stays queryable.
14
+ * - `session.peer_action_*` and `session.host_action_*`: use the
15
+ * per-message `messageId` as flowId so that received→processed /
16
+ * received→failed and sent→response→failed triples line up.
17
+ *
18
+ * Mark anything subscribed to this taxonomy as EXPERIMENTAL on the
19
+ * consumer side — events and payloads may evolve across minor
20
+ * versions.
21
+ */
22
+ export type SsoDebugEvent = {
23
+ layer: 'sso';
24
+ event: 'pairing_started';
25
+ flowId: string;
26
+ timestamp: number;
27
+ payload: {
28
+ metadata: string;
29
+ };
30
+ } | {
31
+ layer: 'sso';
32
+ event: 'deeplink_generated';
33
+ flowId: string;
34
+ timestamp: number;
35
+ payload: {
36
+ deeplink: string;
37
+ };
38
+ } | {
39
+ layer: 'sso';
40
+ event: 'awaiting_response';
41
+ flowId: string;
42
+ timestamp: number;
43
+ payload: {
44
+ topic: string;
45
+ };
46
+ } | {
47
+ layer: 'sso';
48
+ event: 'response_received';
49
+ flowId: string;
50
+ timestamp: number;
51
+ payload: {
52
+ sessionId: string;
53
+ };
54
+ } | {
55
+ layer: 'sso';
56
+ event: 'session_established';
57
+ flowId: string;
58
+ timestamp: number;
59
+ payload: {
60
+ sessionId: string;
61
+ };
62
+ } | {
63
+ layer: 'sso';
64
+ event: 'pairing_failed';
65
+ flowId: string;
66
+ timestamp: number;
67
+ payload: {
68
+ reason: string;
69
+ };
70
+ };
71
+ export type AttestationDebugEvent = {
72
+ layer: 'attestation';
73
+ event: 'started';
74
+ flowId: string;
75
+ timestamp: number;
76
+ payload: {
77
+ candidateAccountId: string;
78
+ };
79
+ } | {
80
+ layer: 'attestation';
81
+ event: 'username_claimed';
82
+ flowId: string;
83
+ timestamp: number;
84
+ payload: {
85
+ username: string;
86
+ };
87
+ } | {
88
+ layer: 'attestation';
89
+ event: 'allowance_granted';
90
+ flowId: string;
91
+ timestamp: number;
92
+ payload: {
93
+ verifierAccountId: string;
94
+ };
95
+ } | {
96
+ layer: 'attestation';
97
+ event: 'vrf_proof_generated';
98
+ flowId: string;
99
+ timestamp: number;
100
+ payload: {
101
+ candidateAccountId: string;
102
+ };
103
+ } | {
104
+ layer: 'attestation';
105
+ event: 'person_registered';
106
+ flowId: string;
107
+ timestamp: number;
108
+ payload: {
109
+ username: string;
110
+ candidateAccountId: string;
111
+ };
112
+ } | {
113
+ layer: 'attestation';
114
+ event: 'completed';
115
+ flowId: string;
116
+ timestamp: number;
117
+ payload: {
118
+ username: string;
119
+ };
120
+ } | {
121
+ layer: 'attestation';
122
+ event: 'failed';
123
+ flowId: string;
124
+ timestamp: number;
125
+ payload: {
126
+ reason: string;
127
+ };
128
+ };
129
+ export type SessionDebugEvent = {
130
+ layer: 'session';
131
+ event: 'opened';
132
+ flowId: string;
133
+ timestamp: number;
134
+ payload: {
135
+ sessionId: string;
136
+ };
137
+ } | {
138
+ layer: 'session';
139
+ event: 'peer_action_received';
140
+ flowId: string;
141
+ timestamp: number;
142
+ payload: {
143
+ sessionId: string;
144
+ messageId: string;
145
+ actionKind: string;
146
+ };
147
+ } | {
148
+ layer: 'session';
149
+ event: 'peer_action_processed';
150
+ flowId: string;
151
+ timestamp: number;
152
+ payload: {
153
+ sessionId: string;
154
+ messageId: string;
155
+ };
156
+ } | {
157
+ layer: 'session';
158
+ event: 'peer_action_failed';
159
+ flowId: string;
160
+ timestamp: number;
161
+ payload: {
162
+ sessionId: string;
163
+ messageId: string;
164
+ reason: string;
165
+ };
166
+ } | {
167
+ layer: 'session';
168
+ event: 'host_action_sent';
169
+ flowId: string;
170
+ timestamp: number;
171
+ payload: {
172
+ sessionId: string;
173
+ messageId: string;
174
+ actionKind: string;
175
+ };
176
+ } | {
177
+ layer: 'session';
178
+ event: 'host_action_response_received';
179
+ flowId: string;
180
+ timestamp: number;
181
+ payload: {
182
+ sessionId: string;
183
+ messageId: string;
184
+ };
185
+ } | {
186
+ layer: 'session';
187
+ event: 'host_action_failed';
188
+ flowId: string;
189
+ timestamp: number;
190
+ payload: {
191
+ sessionId: string;
192
+ messageId: string;
193
+ reason: string;
194
+ };
195
+ } | {
196
+ layer: 'session';
197
+ event: 'terminated';
198
+ flowId: string;
199
+ timestamp: number;
200
+ payload: {
201
+ sessionId: string;
202
+ };
203
+ };
204
+ export type HostPappDebugEvent = SsoDebugEvent | AttestationDebugEvent | SessionDebugEvent;
@@ -0,0 +1 @@
1
+ export {};
@@ -4,6 +4,7 @@ import { generateMnemonic } from '@polkadot-labs/hdkd-helpers';
4
4
  import { Result, ResultAsync, err, fromPromise, fromThrowable, ok } from 'neverthrow';
5
5
  import { mergeUint8, toHex } from 'polkadot-api/utils';
6
6
  import { createEncrSecret, createSharedSecret, deriveSr25519Account, getEncrPub, stringToBytes } from '../../crypto.js';
7
+ import { createFlowId, emitHostPappDebugMessage } from '../../debugBus.js';
7
8
  import { AbortError } from '../../helpers/abortError.js';
8
9
  import { createState, readonly } from '../../helpers/state.js';
9
10
  import { toError } from '../../helpers/utils.js';
@@ -13,7 +14,7 @@ export function createAuth({ metadata, hostMetadata, statementStore, ssoSessionR
13
14
  const pairingStatus = createState({ step: 'none' });
14
15
  let authResult = null;
15
16
  let abort = null;
16
- function handshake(account, signal) {
17
+ function handshake(account, signal, flowId) {
17
18
  const localAccount = createLocalSessionAccount(createAccountId(account.publicKey));
18
19
  pairingStatus.write({ step: 'initial' });
19
20
  const encrKeys = createEncrKeys(account.entropy);
@@ -24,9 +25,26 @@ export function createAuth({ metadata, hostMetadata, statementStore, ssoSessionR
24
25
  hostMetadata,
25
26
  }));
26
27
  const handshakeTopic = encrKeys.andThen(({ publicKey }) => createHandshakeTopic(localAccount, publicKey));
27
- const dataPrepared = Result.combine([handshakePayload, handshakeTopic, encrKeys]).andTee(([payload]) => pairingStatus.write({ step: 'pairing', payload: createDeeplink(payload) }));
28
+ const dataPrepared = Result.combine([handshakePayload, handshakeTopic, encrKeys]).andTee(([payload]) => {
29
+ const deeplink = createDeeplink(payload);
30
+ pairingStatus.write({ step: 'pairing', payload: deeplink });
31
+ emitHostPappDebugMessage({
32
+ layer: 'sso',
33
+ event: 'deeplink_generated',
34
+ flowId,
35
+ timestamp: Date.now(),
36
+ payload: { deeplink },
37
+ });
38
+ });
28
39
  return dataPrepared
29
40
  .asyncAndThen(([, handshakeTopic, encrKeys]) => {
41
+ emitHostPappDebugMessage({
42
+ layer: 'sso',
43
+ event: 'awaiting_response',
44
+ flowId,
45
+ timestamp: Date.now(),
46
+ payload: { topic: toHex(handshakeTopic) },
47
+ });
30
48
  const pappResponse = waitForStatements(callback => statementStore.subscribeStatements({ matchAll: [handshakeTopic] }, page => callback(page.statements)), signal, (statements, resolve) => {
31
49
  for (const statement of statements) {
32
50
  if (!statement.data)
@@ -37,6 +55,13 @@ export function createAuth({ metadata, hostMetadata, statementStore, ssoSessionR
37
55
  payload: statement.data,
38
56
  }).unwrapOr(null);
39
57
  if (session) {
58
+ emitHostPappDebugMessage({
59
+ layer: 'sso',
60
+ event: 'response_received',
61
+ flowId,
62
+ timestamp: Date.now(),
63
+ payload: { sessionId: session.id },
64
+ });
40
65
  resolve(session);
41
66
  break;
42
67
  }
@@ -69,7 +94,15 @@ export function createAuth({ metadata, hostMetadata, statementStore, ssoSessionR
69
94
  }
70
95
  abort = new AbortController();
71
96
  const account = deriveSr25519Account(generateMnemonic(), '//wallet//sso');
72
- authResult = handshake(account, abort.signal)
97
+ const ssoFlowId = createFlowId();
98
+ emitHostPappDebugMessage({
99
+ layer: 'sso',
100
+ event: 'pairing_started',
101
+ flowId: ssoFlowId,
102
+ timestamp: Date.now(),
103
+ payload: { metadata },
104
+ });
105
+ authResult = handshake(account, abort.signal, ssoFlowId)
73
106
  .andThen(({ session, secretsPayload }) => {
74
107
  return userSecretRepository
75
108
  .write(secretsPayload.id, {
@@ -79,14 +112,32 @@ export function createAuth({ metadata, hostMetadata, statementStore, ssoSessionR
79
112
  })
80
113
  .andThen(() => ssoSessionRepository.add(session))
81
114
  .map(() => session);
115
+ })
116
+ .andTee(session => {
117
+ if (session) {
118
+ emitHostPappDebugMessage({
119
+ layer: 'sso',
120
+ event: 'session_established',
121
+ flowId: ssoFlowId,
122
+ timestamp: Date.now(),
123
+ payload: { sessionId: session.id },
124
+ });
125
+ }
82
126
  })
83
127
  .orElse(e => (e instanceof AbortError ? ok(null) : err(e)))
84
128
  .andTee(() => {
85
129
  abort = null;
86
130
  })
87
- .orTee(() => {
131
+ .orTee(e => {
88
132
  authResult = null;
89
133
  abort = null;
134
+ emitHostPappDebugMessage({
135
+ layer: 'sso',
136
+ event: 'pairing_failed',
137
+ flowId: ssoFlowId,
138
+ timestamp: Date.now(),
139
+ payload: { reason: e.message },
140
+ });
90
141
  });
91
142
  return authResult;
92
143
  },
@@ -1,5 +1,6 @@
1
1
  import { createEncryption } from '@novasamatech/statement-store';
2
2
  import { okAsync } from 'neverthrow';
3
+ import { emitHostPappDebugMessage } from '../../debugBus.js';
3
4
  import { createState } from '../../helpers/state.js';
4
5
  import { createSsoStatementProver } from '../ssoSessionProver.js';
5
6
  import { createUserSession } from './userSession.js';
@@ -23,6 +24,13 @@ export function createSsoSessionManager({ ssoSessionRepository, userSecretReposi
23
24
  continue;
24
25
  const session = createSession(userSession, statementStore, storage, userSecretRepository);
25
26
  toAdd.add(session);
27
+ emitHostPappDebugMessage({
28
+ layer: 'session',
29
+ event: 'opened',
30
+ flowId: userSession.id,
31
+ timestamp: Date.now(),
32
+ payload: { sessionId: userSession.id },
33
+ });
26
34
  const unsubscribe = session.subscribe(message => {
27
35
  switch (message.data.tag) {
28
36
  case 'v1': {
@@ -38,6 +46,13 @@ export function createSsoSessionManager({ ssoSessionRepository, userSecretReposi
38
46
  }
39
47
  if (toRemove.size > 0) {
40
48
  for (const id of toRemove) {
49
+ emitHostPappDebugMessage({
50
+ layer: 'session',
51
+ event: 'terminated',
52
+ flowId: id,
53
+ timestamp: Date.now(),
54
+ payload: { sessionId: id },
55
+ });
41
56
  releaseSession(id);
42
57
  activeSessions[id]?.dispose();
43
58
  }
@@ -4,6 +4,7 @@ import { createSession } from '@novasamatech/statement-store';
4
4
  import { fieldListView } from '@novasamatech/storage-adapter';
5
5
  import { nanoid } from 'nanoid';
6
6
  import { ResultAsync, err, ok, okAsync } from 'neverthrow';
7
+ import { emitHostPappDebugMessage } from '../../debugBus.js';
7
8
  import { createAsyncTaskPool } from '../../helpers/createAsyncTaskPool.js';
8
9
  import { toError } from '../../helpers/utils.js';
9
10
  import { RemoteMessageCodec } from './scale/remoteMessage.js';
@@ -16,6 +17,51 @@ function withQueueTimeout(resultAsync, label) {
16
17
  const timeoutPromise = new Promise(resolve => setTimeout(() => resolve(err(new Error(`${label} timed out — queue freed`))), QUEUE_TASK_TIMEOUT_MS));
17
18
  return ResultAsync.fromPromise(Promise.race([resultAsync, timeoutPromise]), toError).andThen(r => r);
18
19
  }
20
+ /**
21
+ * Derive a stable `actionKind` label from a remote-message envelope.
22
+ * Shape: `OuterTag` for flat variants, `OuterTag:InnerTag` for variants
23
+ * whose payload is itself an enum (currently just `SignRequest`).
24
+ * The receive side and the send side both go through here so debug
25
+ * consumers see the same shape regardless of direction.
26
+ */
27
+ function actionKindFromMessageData(data) {
28
+ if (data.tag !== 'v1')
29
+ return data.tag;
30
+ const inner = data.value;
31
+ if (inner.tag === 'SignRequest')
32
+ return `SignRequest:${inner.value.tag}`;
33
+ return inner.tag;
34
+ }
35
+ function emitHostAction(messageId, actionKind, sessionId) {
36
+ emitHostPappDebugMessage({
37
+ layer: 'session',
38
+ event: 'host_action_sent',
39
+ flowId: messageId,
40
+ timestamp: Date.now(),
41
+ payload: { sessionId, messageId, actionKind },
42
+ });
43
+ }
44
+ function withHostActionTrace(result, messageId, sessionId) {
45
+ return result
46
+ .andTee(() => {
47
+ emitHostPappDebugMessage({
48
+ layer: 'session',
49
+ event: 'host_action_response_received',
50
+ flowId: messageId,
51
+ timestamp: Date.now(),
52
+ payload: { sessionId, messageId },
53
+ });
54
+ })
55
+ .orTee(error => {
56
+ emitHostPappDebugMessage({
57
+ layer: 'session',
58
+ event: 'host_action_failed',
59
+ flowId: messageId,
60
+ timestamp: Date.now(),
61
+ payload: { sessionId, messageId, reason: error.message },
62
+ });
63
+ });
64
+ }
19
65
  export function createUserSession({ userSession, statementStore, encryption, storage, prover, }) {
20
66
  const requestQueue = createAsyncTaskPool({ poolSize: 1, retryCount: 0, retryDelay: 0 });
21
67
  const session = createSession({
@@ -39,10 +85,9 @@ export function createUserSession({ userSession, statementStore, encryption, sto
39
85
  signPayload(payload) {
40
86
  return requestQueue.call(() => {
41
87
  const messageId = nanoid();
42
- const request = session.request(RemoteMessageCodec, {
43
- messageId,
44
- data: enumValue('v1', enumValue('SignRequest', enumValue('Payload', payload))),
45
- });
88
+ const data = enumValue('v1', enumValue('SignRequest', enumValue('Payload', payload)));
89
+ emitHostAction(messageId, actionKindFromMessageData(data), userSession.id);
90
+ const request = session.request(RemoteMessageCodec, { messageId, data });
46
91
  const responseFilter = (message) => {
47
92
  if (message.data.tag === 'v1' &&
48
93
  message.data.value.tag === 'SignResponse' &&
@@ -60,16 +105,15 @@ export function createUserSession({ userSession, statementStore, encryption, sto
60
105
  return err(new Error(message.value));
61
106
  }
62
107
  });
63
- return withQueueTimeout(inner, 'signPayload');
108
+ return withHostActionTrace(withQueueTimeout(inner, 'signPayload'), messageId, userSession.id);
64
109
  });
65
110
  },
66
111
  signRaw(payload) {
67
112
  return requestQueue.call(() => {
68
113
  const messageId = nanoid();
69
- const request = session.request(RemoteMessageCodec, {
70
- messageId,
71
- data: enumValue('v1', enumValue('SignRequest', enumValue('Raw', payload))),
72
- });
114
+ const data = enumValue('v1', enumValue('SignRequest', enumValue('Raw', payload)));
115
+ emitHostAction(messageId, actionKindFromMessageData(data), userSession.id);
116
+ const request = session.request(RemoteMessageCodec, { messageId, data });
73
117
  const responseFilter = (message) => {
74
118
  if (message.data.tag === 'v1' &&
75
119
  message.data.value.tag === 'SignResponse' &&
@@ -87,7 +131,7 @@ export function createUserSession({ userSession, statementStore, encryption, sto
87
131
  return err(new Error(message.value));
88
132
  }
89
133
  });
90
- return withQueueTimeout(inner, 'signRaw');
134
+ return withHostActionTrace(withQueueTimeout(inner, 'signRaw'), messageId, userSession.id);
91
135
  });
92
136
  },
93
137
  createTransaction(payload) {
@@ -128,13 +172,12 @@ export function createUserSession({ userSession, statementStore, encryption, sto
128
172
  getRingVrfAlias(productAccountId, productId) {
129
173
  return requestQueue.call(() => {
130
174
  const messageId = nanoid();
131
- const request = session.request(RemoteMessageCodec, {
132
- messageId,
133
- data: enumValue('v1', enumValue('RingVrfAliasRequest', {
134
- productAccountId,
135
- productId,
136
- })),
137
- });
175
+ const data = enumValue('v1', enumValue('RingVrfAliasRequest', {
176
+ productAccountId,
177
+ productId,
178
+ }));
179
+ emitHostAction(messageId, actionKindFromMessageData(data), userSession.id);
180
+ const request = session.request(RemoteMessageCodec, { messageId, data });
138
181
  const responseFilter = (message) => {
139
182
  if (message.data.tag === 'v1' &&
140
183
  message.data.value.tag === 'RingVrfAliasResponse' &&
@@ -142,9 +185,9 @@ export function createUserSession({ userSession, statementStore, encryption, sto
142
185
  return message.data.value.value.payload;
143
186
  }
144
187
  };
145
- return request
188
+ return withHostActionTrace(request
146
189
  .andThen(() => session.waitForRequestMessage(RemoteMessageCodec, responseFilter))
147
- .andThen(result => (result.success ? ok(result.value) : err(new Error(result.value))));
190
+ .andThen(result => (result.success ? ok(result.value) : err(new Error(result.value)))), messageId, userSession.id);
148
191
  });
149
192
  },
150
193
  requestResourceAllocation(request) {
@@ -179,9 +222,36 @@ export function createUserSession({ userSession, statementStore, encryption, sto
179
222
  if (isMessageProcessed) {
180
223
  return okAsync({ processed: false });
181
224
  }
225
+ const messageId = payload.value.messageId;
226
+ const actionKind = actionKindFromMessageData(payload.value.data);
227
+ emitHostPappDebugMessage({
228
+ layer: 'session',
229
+ event: 'peer_action_received',
230
+ flowId: messageId,
231
+ timestamp: Date.now(),
232
+ payload: { sessionId: userSession.id, messageId, actionKind },
233
+ });
182
234
  return callback(payload.value)
235
+ .andTee(processed => {
236
+ if (processed) {
237
+ emitHostPappDebugMessage({
238
+ layer: 'session',
239
+ event: 'peer_action_processed',
240
+ flowId: messageId,
241
+ timestamp: Date.now(),
242
+ payload: { sessionId: userSession.id, messageId },
243
+ });
244
+ }
245
+ })
183
246
  .orTee(error => {
184
247
  console.error('Error while processing sso message:', error);
248
+ emitHostPappDebugMessage({
249
+ layer: 'session',
250
+ event: 'peer_action_failed',
251
+ flowId: messageId,
252
+ timestamp: Date.now(),
253
+ payload: { sessionId: userSession.id, messageId, reason: error.message },
254
+ });
185
255
  })
186
256
  .orElse(() => okAsync(false))
187
257
  .map(processed => (processed ? { processed, message: payload.value } : { processed }));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@novasamatech/host-papp",
3
3
  "type": "module",
4
- "version": "0.7.9-5",
4
+ "version": "0.7.9",
5
5
  "description": "Polkadot app integration",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -18,6 +18,11 @@
18
18
  "#/source": "./src/index.ts",
19
19
  "types": "./dist/index.d.ts",
20
20
  "default": "./dist/index.js"
21
+ },
22
+ "./debug": {
23
+ "#/source": "./src/debug-public.ts",
24
+ "types": "./dist/debug-public.d.ts",
25
+ "default": "./dist/debug-public.js"
21
26
  }
22
27
  },
23
28
  "files": [
@@ -29,10 +34,10 @@
29
34
  "@noble/ciphers": "2.2.0",
30
35
  "@noble/curves": "2.2.0",
31
36
  "@noble/hashes": "2.2.0",
32
- "@novasamatech/host-api": "0.7.9-5",
33
- "@novasamatech/scale": "0.7.9-5",
34
- "@novasamatech/statement-store": "0.7.9-5",
35
- "@novasamatech/storage-adapter": "0.7.9-5",
37
+ "@novasamatech/host-api": "0.7.9",
38
+ "@novasamatech/scale": "0.7.9",
39
+ "@novasamatech/statement-store": "0.7.9",
40
+ "@novasamatech/storage-adapter": "0.7.9",
36
41
  "@polkadot-labs/hdkd-helpers": "^0.0.30",
37
42
  "nanoevents": "9.1.0",
38
43
  "nanoid": "5.1.9",