@nxgt/janus-telemetry 0.10.1 → 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.
- package/README.md +2 -2
- package/dist/flows/events.d.ts.map +1 -1
- package/dist/flows/fields.d.ts +2 -0
- package/dist/flows/fields.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +4 -4
- package/docs/guide/tracing.md +14 -0
- package/docs/roadmap.md +5 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ current span. Like `@nxgt/janus`, it expects `"moduleResolution": "bundler"`.
|
|
|
54
54
|
|
|
55
55
|
| Span | Attributes |
|
|
56
56
|
| --- | --- |
|
|
57
|
-
| `janus.<flow>`, `janus.<type>.<flow>` — `janus.secondFactor.confirm`, `janus.signInCode.confirm`, `janus.magicLink.confirm` and `janus.
|
|
57
|
+
| `janus.<flow>`, `janus.<type>.<flow>` — `janus.secondFactor.confirm`, `janus.signInCode.confirm`, `janus.magicLink.confirm`, `janus.signInProven` and `janus.verifyEmail.proveFirst` included, the reads as well — `janus.<type>.findByEmail` among them — and a prepared request's `send()` as `janus.magicLink.prepare.send` | `janus.user.type`; `user.id` once the answer names a user, never the address or login a read was asked for; `janus.session.renewed` for `authenticate`; `janus.signIn.status` for `signIn`, `signInCode.confirm`, `magicLink.confirm` and `signInProven` — `signedIn`, or `secondFactor` when it answered a challenge; for `stepUp.confirm`, the `user.id` of the session it stamped, never the session's id |
|
|
58
58
|
| `janus.can` | `janus.subject.type`, `janus.subject.id`, `janus.permission`, `janus.object.type`, `janus.object.id`, and the answer, `janus.allowed` |
|
|
59
59
|
| `janus.list` | the subject, `janus.permission`, `janus.object.type`, and `janus.page.items`, how many it found |
|
|
60
60
|
| `janus.grant`, `janus.revoke` | the object, `janus.relation`, and the subject — `janus.subject.relation` for a subject set, read as `permissions()` reads it: a user with a field named `relation` is that user, and a set on a user type is one only when `setOf()` made it |
|
|
@@ -91,7 +91,7 @@ when the flow knows them — `janus.signOut` carries neither:
|
|
|
91
91
|
| `janus.user.deleted` | info | a user was deleted |
|
|
92
92
|
| `janus.user.activated`, `janus.user.deactivated` | info | `setActive` |
|
|
93
93
|
| `janus.password.changed`, `janus.password.set`, `janus.password.reset` | info | the user's change, an admin's, a reset |
|
|
94
|
-
| `janus.email.verified` | info | an e-mail was confirmed |
|
|
94
|
+
| `janus.email.verified` | info | an e-mail was confirmed — by `verifyEmail.confirm`, or proved on the application's own proof by `verifyEmail.proveFirst`, which adds `janus.email.proveFirst: true` and writes it only when it proved (an e-mail already proved writes nothing) |
|
|
95
95
|
| `janus.tuple.granted`, `janus.tuple.revoked` | info | a tuple was written, with the object, relation and subject |
|
|
96
96
|
|
|
97
97
|
## Traps
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/flows/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/flows/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AA0FnC;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,QAAQ,CAC7B,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC,CAkJtD,CAAC"}
|
package/dist/flows/fields.d.ts
CHANGED
|
@@ -28,4 +28,6 @@ export declare function recoveryCodesLeft(value: unknown): number | undefined;
|
|
|
28
28
|
export declare function sessionUserFields(call: Call, value: unknown): Fields;
|
|
29
29
|
/** How a step-up is confirmed — `email` or `secondFactor` — when the answer says. */
|
|
30
30
|
export declare function viaOf(value: unknown): string | undefined;
|
|
31
|
+
/** `verifyEmail.proveFirst`'s `proved`: whether the call proved the e-mail. */
|
|
32
|
+
export declare function provedOf(value: unknown): boolean;
|
|
31
33
|
//# sourceMappingURL=fields.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/flows/fields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,KAAK,MAAM,EAA0B,MAAM,WAAW,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAS7D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAUjE;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CASrE;AAED,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAK/C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,CAQrE;AAED,oDAAoD;AACpD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAO3D;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOpE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CASpE;AAED,qFAAqF;AACrF,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOxD"}
|
|
1
|
+
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/flows/fields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,KAAK,MAAM,EAA0B,MAAM,WAAW,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAS7D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAUjE;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CASrE;AAED,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAK/C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,CAQrE;AAED,oDAAoD;AACpD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAO3D;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOpE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CASpE;AAED,qFAAqF;AACrF,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOxD;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOhD"}
|
package/dist/index.js
CHANGED
|
@@ -142,6 +142,9 @@ function sessionUserFields(call, value) {
|
|
|
142
142
|
function viaOf(value) {
|
|
143
143
|
return typeof value === "object" && value !== null && "via" in value && typeof value.via === "string" ? value.via : undefined;
|
|
144
144
|
}
|
|
145
|
+
function provedOf(value) {
|
|
146
|
+
return typeof value === "object" && value !== null && "proved" in value && value.proved === true;
|
|
147
|
+
}
|
|
145
148
|
|
|
146
149
|
// src/flows/mail.ts
|
|
147
150
|
import { createLogger, event } from "@nxgt/telemetry";
|
|
@@ -333,6 +336,14 @@ var WRITTEN = {
|
|
|
333
336
|
"verifyEmail.confirm": (call, outcome) => {
|
|
334
337
|
if (outcome.ok)
|
|
335
338
|
log2.info(events.emailVerified(userFields(call, outcome.value)));
|
|
339
|
+
},
|
|
340
|
+
"verifyEmail.proveFirst": (call, outcome) => {
|
|
341
|
+
if (outcome.ok && provedOf(outcome.value)) {
|
|
342
|
+
log2.info(events.emailVerified({
|
|
343
|
+
...userFields(call, outcome.value),
|
|
344
|
+
"janus.email.proveFirst": true
|
|
345
|
+
}));
|
|
346
|
+
}
|
|
336
347
|
}
|
|
337
348
|
};
|
|
338
349
|
|
|
@@ -469,5 +480,5 @@ export {
|
|
|
469
480
|
instrumentPermissions
|
|
470
481
|
};
|
|
471
482
|
|
|
472
|
-
//# debugId=
|
|
483
|
+
//# debugId=F208819435F0AAFC64756E2164756E21
|
|
473
484
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
"sources": ["../src/traced.ts", "../src/flows/events.ts", "../src/flows/fields.ts", "../src/flows/mail.ts", "../src/flows/trace.ts", "../src/flows/index.ts", "../src/permissions.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { JanusError, type JanusErrorCode } from '@nxgt/janus';\nimport { type SpanScope, span } from '@nxgt/telemetry';\n\n/**\n * What each code is. A **failure** is the server's to fix, and fails its span;\n * a **refusal** — a wrong password, a taken login, a spent token — is an\n * answer, and leaves it `ok`. Exhaustive, so a new code does not compile until\n * it is classified.\n */\nfunction kindOf(code: JanusErrorCode): 'failure' | 'refusal' {\n\tswitch (code) {\n\t\tcase 'STORE_FAILED':\n\t\tcase 'UNSUPPORTED':\n\t\tcase 'PERMISSION_DEPTH':\n\t\tcase 'HASH_UNSUPPORTED':\n\t\t\treturn 'failure';\n\t\tcase 'NOT_FOUND':\n\t\tcase 'LOGIN_TAKEN':\n\t\tcase 'VERSION_CONFLICT':\n\t\tcase 'USER_INVALID':\n\t\tcase 'PASSWORD_TOO_SHORT':\n\t\tcase 'CREDENTIALS_INVALID':\n\t\tcase 'USER_INACTIVE':\n\t\tcase 'STEP_UP_REQUIRED':\n\t\tcase 'TOKEN_UNKNOWN':\n\t\tcase 'TOKEN_SPENT':\n\t\tcase 'TOKEN_EXPIRED':\n\t\tcase 'TOKEN_STALE':\n\t\tcase 'CODE_INVALID':\n\t\tcase 'MAIL_THROTTLED':\n\t\tcase 'SECOND_FACTOR_NOT_ENROLLED':\n\t\tcase 'SECOND_FACTOR_ACTIVE':\n\t\tcase 'INVALID_CURSOR':\n\t\t\treturn 'refusal';\n\t}\n}\n\n/** A `JanusError` the caller caused; anything else, or a failure code, is not. */\nexport function isRefusal(error: unknown): error is JanusError {\n\treturn error instanceof JanusError && kindOf(error.code) === 'refusal';\n}\n\n/** What a span or an event carries: scalars only, and never an absent one. */\nexport type Fields = Readonly<Record<string, string | number | boolean>>;\n\n/** `fields` without its `undefined` values. */\nexport function fieldsOf(\n\tfields: Readonly<Record<string, string | number | boolean | undefined>>,\n): Fields {\n\tconst kept: Record<string, string | number | boolean> = {};\n\tfor (const [key, value] of Object.entries(fields)) {\n\t\tif (value !== undefined) kept[key] = value;\n\t}\n\treturn kept;\n}\n\n/** The `id` of a user reference, a subject or an object — or nothing. */\nexport function idOf(value: unknown): string | undefined {\n\tif (typeof value === 'string') return value;\n\tif (typeof value === 'object' && value !== null && 'id' in value) {\n\t\tconst id: unknown = value.id;\n\t\tif (typeof id === 'string') return id;\n\t}\n\treturn undefined;\n}\n\n/** The `type` of a subject or an object — or nothing. */\nexport function typeOf(value: unknown): string | undefined {\n\tif (typeof value === 'object' && value !== null && 'type' in value) {\n\t\tconst type: unknown = value.type;\n\t\tif (typeof type === 'string') return type;\n\t}\n\treturn undefined;\n}\n\n/** How a traced call ended, for what is written after it. */\nexport type Outcome =\n\t| { readonly ok: true; readonly value: unknown }\n\t| { readonly ok: false; readonly refusal: JanusError };\n\n/**\n * Runs `call` in a span. **A refusal is an answer**: the span ends `ok`, with\n * `janus.refusal` set to its code, and the error is rethrown once the span is\n * over. A failure is rethrown inside it, so the span is `error`, with the\n * store slot and operation a `StoreFailure` names.\n *\n * `after` sees the outcome inside the span, outside the flow's `try`, and a\n * throw from it is dropped: telemetry never changes what a flow answers.\n */\nexport async function traced<T>(\n\tname: string,\n\tfields: Fields,\n\tcall: () => Promise<T>,\n\tafter: (scope: SpanScope, outcome: Outcome) => void,\n): Promise<T> {\n\tconst ended = await span(name, { attributes: fields }, async (scope) => {\n\t\tlet outcome: { ok: true; value: T } | { ok: false; refusal: JanusError };\n\t\ttry {\n\t\t\toutcome = { ok: true, value: await call() };\n\t\t} catch (error) {\n\t\t\tif (error instanceof JanusError) {\n\t\t\t\tscope.attribute('janus.error.code', error.code);\n\t\t\t\tif (error.slot !== undefined)\n\t\t\t\t\tscope.attribute('janus.store.slot', error.slot);\n\t\t\t\tif (error.operation !== undefined) {\n\t\t\t\t\tscope.attribute('janus.store.operation', error.operation);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isRefusal(error)) throw error;\n\t\t\tscope.attribute('janus.refusal', error.code);\n\t\t\toutcome = { ok: false, refusal: error };\n\t\t}\n\t\ttry {\n\t\t\tafter(scope, outcome);\n\t\t} catch {\n\t\t\t// A signal is never worth a flow's answer.\n\t\t}\n\t\treturn outcome;\n\t});\n\tif (!ended.ok) throw ended.refusal;\n\treturn ended.value;\n}\n",
|
|
6
|
-
"import { createLogger, event } from '@nxgt/telemetry';\nimport type { Outcome } from '../traced';\nimport type { Call } from './call';\nimport {\n\targumentUser,\n\trecoveryCodesLeft,\n\trefusalFields,\n\tsecondFactorFields,\n\tsessionUserFields,\n\tsignedInFields,\n\tstatusOf,\n\tuserFields,\n\tviaOf,\n} from './fields';\nimport { mailRequest } from './mail';\n\nconst log = createLogger('@nxgt/janus');\n\n/** The events a security review reads: who signed in, out, up, stepped up, and what changed. */\nconst events = {\n\tsignedUp: event('janus.signUp'),\n\tsignedIn: event('janus.signIn'),\n\tsignInRefused: event('janus.signIn.refused'),\n\tsignInThrottled: event('janus.signIn.throttled'),\n\tsecondFactorAsked: event('janus.signIn.secondFactor'),\n\tsignInCodeSent: event('janus.signInCode.sent'),\n\tmagicLinkSent: event('janus.magicLink.sent'),\n\tstepUpAsked: event('janus.stepUp.asked'),\n\tstepUpConfirmed: event('janus.stepUp.confirmed'),\n\tstepUpRefused: event('janus.stepUp.refused'),\n\tsecondFactorEnrolled: event('janus.secondFactor.enrolled'),\n\tsecondFactorActivated: event('janus.secondFactor.activated'),\n\tsecondFactorDisabled: event('janus.secondFactor.disabled'),\n\trecoveryCodesRegenerated: event(\n\t\t'janus.secondFactor.recoveryCodesRegenerated',\n\t),\n\tsignedOut: event('janus.signOut'),\n\tsignedOutEverywhere: event('janus.signOutEverywhere'),\n\tuserDeleted: event('janus.user.deleted'),\n\tuserActivated: event('janus.user.activated'),\n\tuserDeactivated: event('janus.user.deactivated'),\n\tpasswordChanged: event('janus.password.changed'),\n\tpasswordSet: event('janus.password.set'),\n\tpasswordReset: event('janus.password.reset'),\n\temailVerified: event('janus.email.verified'),\n};\n\n/**\n * What a sign-in other than the password's writes once answered — an\n * e-mailed code or link, or the application's own proof — marked, so an\n * alert on refusals can tell one from another and from a password: a\n * refusal, the second factor asked for, or a sign-in.\n */\nfunction markedSignIn(mark: string): (call: Call, outcome: Outcome) => void {\n\treturn (call, outcome) => {\n\t\tif (!outcome.ok) {\n\t\t\tlog.warn(\n\t\t\t\tevents.signInRefused({\n\t\t\t\t\t...refusalFields(call, outcome.refusal),\n\t\t\t\t\t[mark]: true,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else if (statusOf(outcome.value) === 'secondFactor') {\n\t\t\tlog.info(\n\t\t\t\tevents.secondFactorAsked(secondFactorFields(call, outcome.value)),\n\t\t\t);\n\t\t} else {\n\t\t\tlog.info(\n\t\t\t\tevents.signedIn({\n\t\t\t\t\t...signedInFields(call, outcome.value),\n\t\t\t\t\t[mark]: true,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t};\n}\n\n/**\n * What a sign-in code or link issued writes: `sent`, with its user — only\n * when one was issued, since `null` is nobody and says nothing.\n */\nfunction issued(\n\tsent: typeof events.signInCodeSent,\n): (call: Call, outcome: Outcome) => void {\n\treturn (call, outcome) => {\n\t\tif (outcome.ok && outcome.value !== null) {\n\t\t\tlog.info(sent(userFields(call, outcome.value)));\n\t\t}\n\t};\n}\n\n/**\n * What each flow writes once it answered. Nothing here reads a login, an\n * e-mail, a password or a token: only user types, ids, codes and reasons.\n */\nexport const WRITTEN: Readonly<\n\tRecord<string, (call: Call, outcome: Outcome) => void>\n> = {\n\tsignUp: (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.signedUp(userFields(call, outcome.value)));\n\t},\n\tsignIn: (call, outcome) => {\n\t\tif (!outcome.ok && outcome.refusal.reason === 'throttled') {\n\t\t\t// Too many passwords at one login: no password was compared.\n\t\t\tlog.warn(\n\t\t\t\tevents.signInThrottled({\n\t\t\t\t\t...refusalFields(call, outcome.refusal),\n\t\t\t\t\t'janus.signIn.retryAfter': outcome.refusal.retryAfter,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else if (!outcome.ok) {\n\t\t\tlog.warn(events.signInRefused(refusalFields(call, outcome.refusal)));\n\t\t} else if (statusOf(outcome.value) === 'secondFactor') {\n\t\t\t// The password was right; the session waits for a code.\n\t\t\tlog.info(\n\t\t\t\tevents.secondFactorAsked(secondFactorFields(call, outcome.value)),\n\t\t\t);\n\t\t} else {\n\t\t\tlog.info(events.signedIn(signedInFields(call, outcome.value)));\n\t\t}\n\t},\n\t'signInCode.request': mailRequest(issued(events.signInCodeSent)),\n\t// In two steps: prepare is counted, and send issues — what request writes.\n\t'signInCode.prepare': mailRequest(),\n\t'signInCode.prepare.send': issued(events.signInCodeSent),\n\t'signInCode.confirm': markedSignIn('janus.signIn.code'),\n\t'magicLink.request': mailRequest(issued(events.magicLinkSent)),\n\t'magicLink.prepare': mailRequest(),\n\t'magicLink.prepare.send': issued(events.magicLinkSent),\n\t'magicLink.confirm': markedSignIn('janus.signIn.magicLink'),\n\t// No credential checked here: the application carried the proof.\n\tsignInProven: markedSignIn('janus.signIn.proven'),\n\t'stepUp.request': mailRequest((call, outcome) => {\n\t\t// Which code confirms it — e-mailed, or from the app — never the code.\n\t\tif (outcome.ok) {\n\t\t\tlog.info(\n\t\t\t\tevents.stepUpAsked({\n\t\t\t\t\t...userFields(call, outcome.value),\n\t\t\t\t\t'janus.stepUp.via': viaOf(outcome.value),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}),\n\t'stepUp.confirm': (call, outcome) => {\n\t\tif (outcome.ok) {\n\t\t\tlog.info(events.stepUpConfirmed(sessionUserFields(call, outcome.value)));\n\t\t} else {\n\t\t\tlog.warn(events.stepUpRefused(refusalFields(call, outcome.refusal)));\n\t\t}\n\t},\n\t'secondFactor.confirm': (call, outcome) => {\n\t\tif (outcome.ok) {\n\t\t\tlog.info(\n\t\t\t\tevents.signedIn({\n\t\t\t\t\t...signedInFields(call, outcome.value),\n\t\t\t\t\t'janus.signIn.secondFactor': true,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tlog.warn(events.signInRefused(refusalFields(call, outcome.refusal)));\n\t\t}\n\t},\n\t'secondFactor.recover': (call, outcome) => {\n\t\t// Marked, so an alert can watch sign-ins made without the phone.\n\t\tif (outcome.ok) {\n\t\t\tlog.info(\n\t\t\t\tevents.signedIn({\n\t\t\t\t\t...signedInFields(call, outcome.value),\n\t\t\t\t\t'janus.signIn.recoveryCode': true,\n\t\t\t\t\t'janus.secondFactor.recoveryCodesLeft': recoveryCodesLeft(\n\t\t\t\t\t\toutcome.value,\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tlog.warn(\n\t\t\t\tevents.signInRefused({\n\t\t\t\t\t...refusalFields(call, outcome.refusal),\n\t\t\t\t\t'janus.signIn.recoveryCode': true,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t},\n\t'secondFactor.regenerateRecoveryCodes': (call, outcome) => {\n\t\tif (outcome.ok) {\n\t\t\tlog.info(events.recoveryCodesRegenerated(argumentUser(call)));\n\t\t}\n\t},\n\t'secondFactor.enroll': (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.secondFactorEnrolled(argumentUser(call)));\n\t},\n\t'secondFactor.activate': (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.secondFactorActivated(argumentUser(call)));\n\t},\n\t'secondFactor.disable': (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.secondFactorDisabled(argumentUser(call)));\n\t},\n\tsignOut: (_call, outcome) => {\n\t\tif (outcome.ok && outcome.value === true) log.info(events.signedOut());\n\t},\n\tsignOutEverywhere: (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.signedOutEverywhere(argumentUser(call)));\n\t},\n\tdelete: (call, outcome) => {\n\t\tif (outcome.ok && outcome.value === true) {\n\t\t\tlog.info(events.userDeleted(argumentUser(call)));\n\t\t}\n\t},\n\tsetActive: (call, outcome) => {\n\t\tif (!outcome.ok) return;\n\t\tconst written =\n\t\t\tcall.args[1] === true ? events.userActivated : events.userDeactivated;\n\t\tlog.info(written(argumentUser(call)));\n\t},\n\tchangePassword: (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.passwordChanged(argumentUser(call)));\n\t},\n\tsetPassword: (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.passwordSet(argumentUser(call)));\n\t},\n\t'resetPassword.request': mailRequest(),\n\t'resetPassword.prepare': mailRequest(),\n\t'verifyEmail.send': mailRequest(),\n\t'resetPassword.confirm': (call, outcome) => {\n\t\tif (outcome.ok)\n\t\t\tlog.info(events.passwordReset(userFields(call, outcome.value)));\n\t},\n\t'verifyEmail.confirm': (call, outcome) => {\n\t\tif (outcome.ok)\n\t\t\tlog.info(events.emailVerified(userFields(call, outcome.value)));\n\t},\n};\n",
|
|
7
|
-
"import type { JanusError } from '@nxgt/janus';\nimport { type Fields, fieldsOf, idOf, typeOf } from '../traced';\nimport type { Call } from './call';\n\n/** The user an answer names — `{ user }` or the user itself — as fields. */\nexport function userFields(call: Call, value: unknown): Fields {\n\tconst user =\n\t\ttypeof value === 'object' && value !== null && 'user' in value\n\t\t\t? value.user\n\t\t\t: value;\n\treturn fieldsOf({\n\t\t'janus.user.type': typeOf(user) ?? call.userType,\n\t\t'user.id': idOf(user),\n\t});\n}\n\n/**\n * A session opened: the user, and `janus.signIn.newDevice` when the answer\n * says the device was new to them — never the device token itself.\n */\nexport function signedInFields(call: Call, value: unknown): Fields {\n\tconst newDevice =\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'newDevice' in value &&\n\t\tvalue.newDevice === true;\n\treturn {\n\t\t...userFields(call, value),\n\t\t...(newDevice ? { 'janus.signIn.newDevice': true } : {}),\n\t};\n}\n\n/** Whose sign-in waits for a code: the `userId` the answer carries. */\nexport function secondFactorFields(call: Call, value: unknown): Fields {\n\tconst userId =\n\t\ttypeof value === 'object' && value !== null && 'userId' in value\n\t\t\t? value.userId\n\t\t\t: undefined;\n\treturn fieldsOf({\n\t\t'janus.user.type': call.userType,\n\t\t'user.id': typeof userId === 'string' ? userId : undefined,\n\t});\n}\n\n/** The user a flow was called for: its first argument. */\nexport function argumentUser(call: Call): Fields {\n\treturn fieldsOf({\n\t\t'janus.user.type': call.userType,\n\t\t'user.id': idOf(call.args[0]),\n\t});\n}\n\n/**\n * Why a sign-in was refused: the code, the reason, the user when one holds\n * the login, and what a challenge has left of its attempts.\n */\nexport function refusalFields(call: Call, refusal: JanusError): Fields {\n\treturn fieldsOf({\n\t\t'janus.user.type': refusal.userType ?? call.userType,\n\t\t'janus.refusal': refusal.code,\n\t\t'janus.refusal.reason': refusal.reason,\n\t\t'janus.secondFactor.attemptsLeft': refusal.attemptsLeft,\n\t\t'user.id': refusal.userId,\n\t});\n}\n\n/** `signIn`'s `status`, when the answer has one. */\nexport function statusOf(value: unknown): string | undefined {\n\treturn typeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'status' in value &&\n\t\ttypeof value.status === 'string'\n\t\t? value.status\n\t\t: undefined;\n}\n\n/** How many recovery codes `secondFactor.recover` left: a count, never a code. */\nexport function recoveryCodesLeft(value: unknown): number | undefined {\n\treturn typeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'recoveryCodesLeft' in value &&\n\t\ttypeof value.recoveryCodesLeft === 'number'\n\t\t? value.recoveryCodesLeft\n\t\t: undefined;\n}\n\n/**\n * The user a session names — what `stepUp.confirm` answers — by its\n * `userId`: the session's own id is not the user's.\n */\nexport function sessionUserFields(call: Call, value: unknown): Fields {\n\tconst userId =\n\t\ttypeof value === 'object' && value !== null && 'userId' in value\n\t\t\t? value.userId\n\t\t\t: undefined;\n\treturn fieldsOf({\n\t\t'janus.user.type': call.userType,\n\t\t'user.id': typeof userId === 'string' ? userId : undefined,\n\t});\n}\n\n/** How a step-up is confirmed — `email` or `secondFactor` — when the answer says. */\nexport function viaOf(value: unknown): string | undefined {\n\treturn typeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'via' in value &&\n\t\ttypeof value.via === 'string'\n\t\t? value.via\n\t\t: undefined;\n}\n",
|
|
6
|
+
"import { createLogger, event } from '@nxgt/telemetry';\nimport type { Outcome } from '../traced';\nimport type { Call } from './call';\nimport {\n\targumentUser,\n\tprovedOf,\n\trecoveryCodesLeft,\n\trefusalFields,\n\tsecondFactorFields,\n\tsessionUserFields,\n\tsignedInFields,\n\tstatusOf,\n\tuserFields,\n\tviaOf,\n} from './fields';\nimport { mailRequest } from './mail';\n\nconst log = createLogger('@nxgt/janus');\n\n/** The events a security review reads: who signed in, out, up, stepped up, and what changed. */\nconst events = {\n\tsignedUp: event('janus.signUp'),\n\tsignedIn: event('janus.signIn'),\n\tsignInRefused: event('janus.signIn.refused'),\n\tsignInThrottled: event('janus.signIn.throttled'),\n\tsecondFactorAsked: event('janus.signIn.secondFactor'),\n\tsignInCodeSent: event('janus.signInCode.sent'),\n\tmagicLinkSent: event('janus.magicLink.sent'),\n\tstepUpAsked: event('janus.stepUp.asked'),\n\tstepUpConfirmed: event('janus.stepUp.confirmed'),\n\tstepUpRefused: event('janus.stepUp.refused'),\n\tsecondFactorEnrolled: event('janus.secondFactor.enrolled'),\n\tsecondFactorActivated: event('janus.secondFactor.activated'),\n\tsecondFactorDisabled: event('janus.secondFactor.disabled'),\n\trecoveryCodesRegenerated: event(\n\t\t'janus.secondFactor.recoveryCodesRegenerated',\n\t),\n\tsignedOut: event('janus.signOut'),\n\tsignedOutEverywhere: event('janus.signOutEverywhere'),\n\tuserDeleted: event('janus.user.deleted'),\n\tuserActivated: event('janus.user.activated'),\n\tuserDeactivated: event('janus.user.deactivated'),\n\tpasswordChanged: event('janus.password.changed'),\n\tpasswordSet: event('janus.password.set'),\n\tpasswordReset: event('janus.password.reset'),\n\temailVerified: event('janus.email.verified'),\n};\n\n/**\n * What a sign-in other than the password's writes once answered — an\n * e-mailed code or link, or the application's own proof — marked, so an\n * alert on refusals can tell one from another and from a password: a\n * refusal, the second factor asked for, or a sign-in.\n */\nfunction markedSignIn(mark: string): (call: Call, outcome: Outcome) => void {\n\treturn (call, outcome) => {\n\t\tif (!outcome.ok) {\n\t\t\tlog.warn(\n\t\t\t\tevents.signInRefused({\n\t\t\t\t\t...refusalFields(call, outcome.refusal),\n\t\t\t\t\t[mark]: true,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else if (statusOf(outcome.value) === 'secondFactor') {\n\t\t\tlog.info(\n\t\t\t\tevents.secondFactorAsked(secondFactorFields(call, outcome.value)),\n\t\t\t);\n\t\t} else {\n\t\t\tlog.info(\n\t\t\t\tevents.signedIn({\n\t\t\t\t\t...signedInFields(call, outcome.value),\n\t\t\t\t\t[mark]: true,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t};\n}\n\n/**\n * What a sign-in code or link issued writes: `sent`, with its user — only\n * when one was issued, since `null` is nobody and says nothing.\n */\nfunction issued(\n\tsent: typeof events.signInCodeSent,\n): (call: Call, outcome: Outcome) => void {\n\treturn (call, outcome) => {\n\t\tif (outcome.ok && outcome.value !== null) {\n\t\t\tlog.info(sent(userFields(call, outcome.value)));\n\t\t}\n\t};\n}\n\n/**\n * What each flow writes once it answered. Nothing here reads a login, an\n * e-mail, a password or a token: only user types, ids, codes and reasons.\n */\nexport const WRITTEN: Readonly<\n\tRecord<string, (call: Call, outcome: Outcome) => void>\n> = {\n\tsignUp: (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.signedUp(userFields(call, outcome.value)));\n\t},\n\tsignIn: (call, outcome) => {\n\t\tif (!outcome.ok && outcome.refusal.reason === 'throttled') {\n\t\t\t// Too many passwords at one login: no password was compared.\n\t\t\tlog.warn(\n\t\t\t\tevents.signInThrottled({\n\t\t\t\t\t...refusalFields(call, outcome.refusal),\n\t\t\t\t\t'janus.signIn.retryAfter': outcome.refusal.retryAfter,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else if (!outcome.ok) {\n\t\t\tlog.warn(events.signInRefused(refusalFields(call, outcome.refusal)));\n\t\t} else if (statusOf(outcome.value) === 'secondFactor') {\n\t\t\t// The password was right; the session waits for a code.\n\t\t\tlog.info(\n\t\t\t\tevents.secondFactorAsked(secondFactorFields(call, outcome.value)),\n\t\t\t);\n\t\t} else {\n\t\t\tlog.info(events.signedIn(signedInFields(call, outcome.value)));\n\t\t}\n\t},\n\t'signInCode.request': mailRequest(issued(events.signInCodeSent)),\n\t// In two steps: prepare is counted, and send issues — what request writes.\n\t'signInCode.prepare': mailRequest(),\n\t'signInCode.prepare.send': issued(events.signInCodeSent),\n\t'signInCode.confirm': markedSignIn('janus.signIn.code'),\n\t'magicLink.request': mailRequest(issued(events.magicLinkSent)),\n\t'magicLink.prepare': mailRequest(),\n\t'magicLink.prepare.send': issued(events.magicLinkSent),\n\t'magicLink.confirm': markedSignIn('janus.signIn.magicLink'),\n\t// No credential checked here: the application carried the proof.\n\tsignInProven: markedSignIn('janus.signIn.proven'),\n\t'stepUp.request': mailRequest((call, outcome) => {\n\t\t// Which code confirms it — e-mailed, or from the app — never the code.\n\t\tif (outcome.ok) {\n\t\t\tlog.info(\n\t\t\t\tevents.stepUpAsked({\n\t\t\t\t\t...userFields(call, outcome.value),\n\t\t\t\t\t'janus.stepUp.via': viaOf(outcome.value),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}),\n\t'stepUp.confirm': (call, outcome) => {\n\t\tif (outcome.ok) {\n\t\t\tlog.info(events.stepUpConfirmed(sessionUserFields(call, outcome.value)));\n\t\t} else {\n\t\t\tlog.warn(events.stepUpRefused(refusalFields(call, outcome.refusal)));\n\t\t}\n\t},\n\t'secondFactor.confirm': (call, outcome) => {\n\t\tif (outcome.ok) {\n\t\t\tlog.info(\n\t\t\t\tevents.signedIn({\n\t\t\t\t\t...signedInFields(call, outcome.value),\n\t\t\t\t\t'janus.signIn.secondFactor': true,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tlog.warn(events.signInRefused(refusalFields(call, outcome.refusal)));\n\t\t}\n\t},\n\t'secondFactor.recover': (call, outcome) => {\n\t\t// Marked, so an alert can watch sign-ins made without the phone.\n\t\tif (outcome.ok) {\n\t\t\tlog.info(\n\t\t\t\tevents.signedIn({\n\t\t\t\t\t...signedInFields(call, outcome.value),\n\t\t\t\t\t'janus.signIn.recoveryCode': true,\n\t\t\t\t\t'janus.secondFactor.recoveryCodesLeft': recoveryCodesLeft(\n\t\t\t\t\t\toutcome.value,\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tlog.warn(\n\t\t\t\tevents.signInRefused({\n\t\t\t\t\t...refusalFields(call, outcome.refusal),\n\t\t\t\t\t'janus.signIn.recoveryCode': true,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t},\n\t'secondFactor.regenerateRecoveryCodes': (call, outcome) => {\n\t\tif (outcome.ok) {\n\t\t\tlog.info(events.recoveryCodesRegenerated(argumentUser(call)));\n\t\t}\n\t},\n\t'secondFactor.enroll': (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.secondFactorEnrolled(argumentUser(call)));\n\t},\n\t'secondFactor.activate': (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.secondFactorActivated(argumentUser(call)));\n\t},\n\t'secondFactor.disable': (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.secondFactorDisabled(argumentUser(call)));\n\t},\n\tsignOut: (_call, outcome) => {\n\t\tif (outcome.ok && outcome.value === true) log.info(events.signedOut());\n\t},\n\tsignOutEverywhere: (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.signedOutEverywhere(argumentUser(call)));\n\t},\n\tdelete: (call, outcome) => {\n\t\tif (outcome.ok && outcome.value === true) {\n\t\t\tlog.info(events.userDeleted(argumentUser(call)));\n\t\t}\n\t},\n\tsetActive: (call, outcome) => {\n\t\tif (!outcome.ok) return;\n\t\tconst written =\n\t\t\tcall.args[1] === true ? events.userActivated : events.userDeactivated;\n\t\tlog.info(written(argumentUser(call)));\n\t},\n\tchangePassword: (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.passwordChanged(argumentUser(call)));\n\t},\n\tsetPassword: (call, outcome) => {\n\t\tif (outcome.ok) log.info(events.passwordSet(argumentUser(call)));\n\t},\n\t'resetPassword.request': mailRequest(),\n\t'resetPassword.prepare': mailRequest(),\n\t'verifyEmail.send': mailRequest(),\n\t'resetPassword.confirm': (call, outcome) => {\n\t\tif (outcome.ok)\n\t\t\tlog.info(events.passwordReset(userFields(call, outcome.value)));\n\t},\n\t'verifyEmail.confirm': (call, outcome) => {\n\t\tif (outcome.ok)\n\t\t\tlog.info(events.emailVerified(userFields(call, outcome.value)));\n\t},\n\t// Only when it proved: an e-mail already proved changed nothing.\n\t'verifyEmail.proveFirst': (call, outcome) => {\n\t\tif (outcome.ok && provedOf(outcome.value)) {\n\t\t\tlog.info(\n\t\t\t\tevents.emailVerified({\n\t\t\t\t\t...userFields(call, outcome.value),\n\t\t\t\t\t'janus.email.proveFirst': true,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t},\n};\n",
|
|
7
|
+
"import type { JanusError } from '@nxgt/janus';\nimport { type Fields, fieldsOf, idOf, typeOf } from '../traced';\nimport type { Call } from './call';\n\n/** The user an answer names — `{ user }` or the user itself — as fields. */\nexport function userFields(call: Call, value: unknown): Fields {\n\tconst user =\n\t\ttypeof value === 'object' && value !== null && 'user' in value\n\t\t\t? value.user\n\t\t\t: value;\n\treturn fieldsOf({\n\t\t'janus.user.type': typeOf(user) ?? call.userType,\n\t\t'user.id': idOf(user),\n\t});\n}\n\n/**\n * A session opened: the user, and `janus.signIn.newDevice` when the answer\n * says the device was new to them — never the device token itself.\n */\nexport function signedInFields(call: Call, value: unknown): Fields {\n\tconst newDevice =\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'newDevice' in value &&\n\t\tvalue.newDevice === true;\n\treturn {\n\t\t...userFields(call, value),\n\t\t...(newDevice ? { 'janus.signIn.newDevice': true } : {}),\n\t};\n}\n\n/** Whose sign-in waits for a code: the `userId` the answer carries. */\nexport function secondFactorFields(call: Call, value: unknown): Fields {\n\tconst userId =\n\t\ttypeof value === 'object' && value !== null && 'userId' in value\n\t\t\t? value.userId\n\t\t\t: undefined;\n\treturn fieldsOf({\n\t\t'janus.user.type': call.userType,\n\t\t'user.id': typeof userId === 'string' ? userId : undefined,\n\t});\n}\n\n/** The user a flow was called for: its first argument. */\nexport function argumentUser(call: Call): Fields {\n\treturn fieldsOf({\n\t\t'janus.user.type': call.userType,\n\t\t'user.id': idOf(call.args[0]),\n\t});\n}\n\n/**\n * Why a sign-in was refused: the code, the reason, the user when one holds\n * the login, and what a challenge has left of its attempts.\n */\nexport function refusalFields(call: Call, refusal: JanusError): Fields {\n\treturn fieldsOf({\n\t\t'janus.user.type': refusal.userType ?? call.userType,\n\t\t'janus.refusal': refusal.code,\n\t\t'janus.refusal.reason': refusal.reason,\n\t\t'janus.secondFactor.attemptsLeft': refusal.attemptsLeft,\n\t\t'user.id': refusal.userId,\n\t});\n}\n\n/** `signIn`'s `status`, when the answer has one. */\nexport function statusOf(value: unknown): string | undefined {\n\treturn typeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'status' in value &&\n\t\ttypeof value.status === 'string'\n\t\t? value.status\n\t\t: undefined;\n}\n\n/** How many recovery codes `secondFactor.recover` left: a count, never a code. */\nexport function recoveryCodesLeft(value: unknown): number | undefined {\n\treturn typeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'recoveryCodesLeft' in value &&\n\t\ttypeof value.recoveryCodesLeft === 'number'\n\t\t? value.recoveryCodesLeft\n\t\t: undefined;\n}\n\n/**\n * The user a session names — what `stepUp.confirm` answers — by its\n * `userId`: the session's own id is not the user's.\n */\nexport function sessionUserFields(call: Call, value: unknown): Fields {\n\tconst userId =\n\t\ttypeof value === 'object' && value !== null && 'userId' in value\n\t\t\t? value.userId\n\t\t\t: undefined;\n\treturn fieldsOf({\n\t\t'janus.user.type': call.userType,\n\t\t'user.id': typeof userId === 'string' ? userId : undefined,\n\t});\n}\n\n/** How a step-up is confirmed — `email` or `secondFactor` — when the answer says. */\nexport function viaOf(value: unknown): string | undefined {\n\treturn typeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'via' in value &&\n\t\ttypeof value.via === 'string'\n\t\t? value.via\n\t\t: undefined;\n}\n\n/** `verifyEmail.proveFirst`'s `proved`: whether the call proved the e-mail. */\nexport function provedOf(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'proved' in value &&\n\t\tvalue.proved === true\n\t);\n}\n",
|
|
8
8
|
"import { createLogger, event } from '@nxgt/telemetry';\nimport type { Outcome } from '../traced';\nimport type { Call } from './call';\nimport { refusalFields } from './fields';\n\nconst log = createLogger('@nxgt/janus');\n\n/** Too many e-mails asked for one address, or one user, in a window. */\nconst mailThrottled = event('janus.mail.throttled');\n\ntype Written = (call: Call, outcome: Outcome) => void;\n\n/**\n * What a request that hands out something to e-mail writes: a\n * `janus.mail.throttled` warning when it was refused past its limit — with\n * the flow and the seconds to wait, never the address — and otherwise what\n * `written` writes, if anything.\n */\nexport function mailRequest(written?: Written): Written {\n\treturn (call, outcome) => {\n\t\tif (!outcome.ok && outcome.refusal.code === 'MAIL_THROTTLED') {\n\t\t\t// Nothing was issued, so nothing is sent.\n\t\t\tlog.warn(\n\t\t\t\tmailThrottled({\n\t\t\t\t\t...refusalFields(call, outcome.refusal),\n\t\t\t\t\t'janus.mail.flow': call.flow,\n\t\t\t\t\t...(outcome.refusal.retryAfter === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { 'janus.mail.retryAfter': outcome.refusal.retryAfter }),\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\twritten?.(call, outcome);\n\t};\n}\n",
|
|
9
9
|
"import type { SpanScope } from '@nxgt/telemetry';\nimport { fieldsOf, type Outcome, traced } from '../traced';\nimport type { Call } from './call';\nimport { WRITTEN } from './events';\nimport { sessionUserFields, statusOf, userFields } from './fields';\n\n/** What a span learns from an answer: whose it is, never what it holds. */\nfunction answered(scope: SpanScope, call: Call, outcome: Outcome): void {\n\tif (outcome.ok) {\n\t\t// A session is answered by `stepUp.confirm`: its user is its `userId`.\n\t\tconst fields =\n\t\t\tcall.flow === 'stepUp.confirm'\n\t\t\t\t? sessionUserFields(call, outcome.value)\n\t\t\t\t: userFields(call, outcome.value);\n\t\tfor (const [key, value] of Object.entries(fields))\n\t\t\tscope.attribute(key, value);\n\t\tconst value = outcome.value;\n\t\tif (typeof value === 'object' && value !== null && 'renewed' in value) {\n\t\t\tscope.attribute('janus.session.renewed', value.renewed === true);\n\t\t}\n\t\tconst status = SIGN_INS.has(call.flow) ? statusOf(value) : undefined;\n\t\tif (status !== undefined) scope.attribute('janus.signIn.status', status);\n\t}\n\tWRITTEN[call.flow]?.(call, outcome);\n}\n\n/** The flows whose answer is a sign-in's: a session, or a second factor asked for. */\nconst SIGN_INS = new Set([\n\t'signIn',\n\t'signInCode.confirm',\n\t'magicLink.confirm',\n\t'signInProven',\n]);\n\n/** `cookie` answers synchronously: it is the one part of `janus()` not traced. */\nconst UNTRACED = new Set(['cookie']);\n\n/** Which user type and flow a path names: `['patient', 'signIn']`. */\ntype Split = (path: readonly string[]) => {\n\treadonly userType: string | undefined;\n\treadonly flow: readonly string[];\n};\n\n/**\n * A traced copy of `target`, frozen: its functions traced, its plain objects —\n * a user type's flows, `verifyEmail` — copied the same way. A copy rather\n * than a Proxy, which may not answer differently for a frozen property.\n */\nexport function traceObject<O extends object>(\n\ttarget: O,\n\tpath: readonly string[],\n\tsplit: Split,\n): O {\n\tconst copy: Record<string, unknown> = {};\n\tfor (const [key, value] of Object.entries(target)) {\n\t\tif (UNTRACED.has(key)) {\n\t\t\tcopy[key] = value;\n\t\t} else if (typeof value === 'function') {\n\t\t\tcopy[key] = traceFunction(\n\t\t\t\tvalue as (...args: unknown[]) => unknown,\n\t\t\t\ttarget,\n\t\t\t\t[...path, key],\n\t\t\t\tsplit,\n\t\t\t);\n\t\t} else if (\n\t\t\ttypeof value === 'object' &&\n\t\t\tvalue !== null &&\n\t\t\t!Array.isArray(value)\n\t\t) {\n\t\t\tcopy[key] = traceObject(value, [...path, key], split);\n\t\t} else {\n\t\t\tcopy[key] = value;\n\t\t}\n\t}\n\treturn Object.freeze(copy) as O;\n}\n\nfunction traceFunction(\n\tfn: (...args: unknown[]) => unknown,\n\tself: object,\n\tpath: readonly string[],\n\tsplit: Split,\n): (...args: unknown[]) => Promise<unknown> {\n\tconst { userType, flow } = split(path);\n\tconst name = `janus.${path.join('.')}`;\n\tconst fields = fieldsOf({ 'janus.user.type': userType });\n\treturn (...args) => {\n\t\tconst call: Call = { flow: flow.join('.'), userType, args };\n\t\tconst answer = traced(\n\t\t\tname,\n\t\t\tfields,\n\t\t\t() => Promise.resolve(fn.apply(self, args)),\n\t\t\t(scope, outcome) => answered(scope, call, outcome),\n\t\t);\n\t\treturn path.at(-1) === 'prepare'\n\t\t\t? answer.then((value) => tracePrepared(value, path, split))\n\t\t\t: answer;\n\t};\n}\n\n/**\n * What `prepare` answers — `magicLink.prepare(email)` — traced in turn, so\n * its `send()` is a span of its own, `janus.magicLink.prepare.send`, and\n * writes what `request` writes once it issued. Anything else is answered\n * as it came.\n */\nfunction tracePrepared(\n\tvalue: unknown,\n\tpath: readonly string[],\n\tsplit: Split,\n): unknown {\n\treturn typeof value === 'object' && value !== null\n\t\t? traceObject(value, path, split)\n\t\t: value;\n}\n",
|
|
10
10
|
"import { traceObject } from './trace';\n\n/** What `janus()` answers, as far as it is read: its user types and its flows. */\nexport interface JanusLike {\n\treadonly types: readonly string[];\n\treadonly authenticate: (...args: never[]) => Promise<unknown>;\n}\n\n/**\n * The same `janus()` instance, with every flow traced — a span per call,\n * named `janus.signIn` or `janus.patient.signIn` — and the events a security\n * review reads written as logs: sign-ups, sign-ins and the reason one was\n * refused, a second factor asked for, enrolled, activated or disabled, a\n * sign-in by recovery code and the codes left, recovery codes regenerated,\n * sign-outs, deleted and deactivated users, changed passwords.\n *\n * ```ts\n * const auth = instrumentJanus(janus({ users, store, hasher }));\n * ```\n *\n * **A refusal is an answer**: a wrong password leaves its span `ok`, with\n * `janus.refusal` set, and is a `janus.signIn.refused` warning — never a\n * failed span. A store that cannot answer is one, with `janus.store.slot`.\n *\n * Nothing written carries a login, an e-mail, a password, a token, a\n * challenge, a code, a TOTP secret or a session id: user types, user ids,\n * codes and reasons only.\n */\nexport function instrumentJanus<A extends JanusLike>(auth: A): A {\n\tconst types = auth.types.filter((type) => typeof type === 'string');\n\tconst only = types.length === 1 ? types[0] : undefined;\n\treturn traceObject(auth, [], (path) =>\n\t\tpath[0] !== undefined && types.includes(path[0])\n\t\t\t? { userType: path[0], flow: path.slice(1) }\n\t\t\t: { userType: only, flow: path },\n\t);\n}\n",
|
|
11
11
|
"import { isSetOf } from '@nxgt/janus';\nimport { createLogger, event, type TelemetryEvent } from '@nxgt/telemetry';\nimport { type Fields, fieldsOf, idOf, traced, typeOf } from './traced';\n\nconst log = createLogger('@nxgt/janus');\n\n/** The audit trail of who was given what: one event per tuple written. */\nconst granted = event('janus.tuple.granted');\nconst revoked = event('janus.tuple.revoked');\n\n/**\n * A subject — a user, an object, or a subject set — as fields, read as\n * `permissions()` reads it: a value of a user type is that user, even with a\n * field named `relation`, unless `setOf()` made it.\n */\nfunction subjectFields(\n\tsubject: unknown,\n\tuserTypes: ReadonlySet<string>,\n): Fields {\n\tconst type = typeOf(subject);\n\tconst relation =\n\t\ttypeof subject === 'object' && subject !== null && 'relation' in subject\n\t\t\t? subject.relation\n\t\t\t: undefined;\n\tconst isSet =\n\t\ttypeof relation === 'string' &&\n\t\t(isSetOf(subject) || type === undefined || !userTypes.has(type));\n\treturn fieldsOf({\n\t\t'janus.subject.type': type,\n\t\t'janus.subject.id': idOf(subject),\n\t\t'janus.subject.relation': isSet ? relation : undefined,\n\t});\n}\n\nfunction objectFields(object: unknown): Fields {\n\treturn fieldsOf({\n\t\t'janus.object.type': typeOf(object),\n\t\t'janus.object.id': idOf(object),\n\t});\n}\n\n/** What `permissions()` answers, as far as it is traced. */\nexport interface PermissionsLike {\n\t/** Its user types tell a user from a subject set of the same shape. */\n\treadonly model?: { readonly subjects: readonly string[] };\n\treadonly can: (...args: never[]) => Promise<boolean>;\n\treadonly list: (...args: never[]) => Promise<unknown>;\n\treadonly grant: (...args: never[]) => Promise<unknown>;\n\treadonly revoke: (...args: never[]) => Promise<unknown>;\n}\n\ntype Traced = (...args: unknown[]) => Promise<unknown>;\n\n/** How each method of `permissions()` is traced. */\nconst tracersFor = (\n\tuserTypes: ReadonlySet<string>,\n): Readonly<Record<string, (fn: Traced) => Traced>> => ({\n\tcan:\n\t\t(fn) =>\n\t\t(...args) =>\n\t\t\ttraced(\n\t\t\t\t'janus.can',\n\t\t\t\tfieldsOf({\n\t\t\t\t\t...subjectFields(args[0], userTypes),\n\t\t\t\t\t'janus.permission': typeof args[1] === 'string' ? args[1] : undefined,\n\t\t\t\t\t...objectFields(args[2]),\n\t\t\t\t}),\n\t\t\t\t() => fn(...args),\n\t\t\t\t(scope, outcome) => {\n\t\t\t\t\tif (outcome.ok)\n\t\t\t\t\t\tscope.attribute('janus.allowed', outcome.value === true);\n\t\t\t\t},\n\t\t\t),\n\tlist:\n\t\t(fn) =>\n\t\t(...args) =>\n\t\t\ttraced(\n\t\t\t\t'janus.list',\n\t\t\t\tfieldsOf({\n\t\t\t\t\t...subjectFields(args[0], userTypes),\n\t\t\t\t\t'janus.permission': typeof args[1] === 'string' ? args[1] : undefined,\n\t\t\t\t\t'janus.object.type':\n\t\t\t\t\t\ttypeof args[2] === 'string' ? args[2] : undefined,\n\t\t\t\t}),\n\t\t\t\t() => fn(...args),\n\t\t\t\t(scope, outcome) => {\n\t\t\t\t\tconst page = outcome.ok ? outcome.value : undefined;\n\t\t\t\t\tif (typeof page === 'object' && page !== null && 'items' in page) {\n\t\t\t\t\t\tconst items = page.items;\n\t\t\t\t\t\tif (Array.isArray(items))\n\t\t\t\t\t\t\tscope.attribute('janus.page.items', items.length);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t),\n\tgrant: (fn) => tupleWrite('janus.grant', granted, fn, userTypes),\n\trevoke: (fn) => tupleWrite('janus.revoke', revoked, fn, userTypes),\n});\n\nfunction tupleWrite(\n\tname: string,\n\twritten: (fields: Fields) => TelemetryEvent,\n\tfn: Traced,\n\tuserTypes: ReadonlySet<string>,\n): Traced {\n\treturn (...args) => {\n\t\tconst fields = fieldsOf({\n\t\t\t...objectFields(args[0]),\n\t\t\t'janus.relation': typeof args[1] === 'string' ? args[1] : undefined,\n\t\t\t...subjectFields(args[2], userTypes),\n\t\t});\n\t\treturn traced(\n\t\t\tname,\n\t\t\tfields,\n\t\t\t() => fn(...args),\n\t\t\t(_scope, outcome) => {\n\t\t\t\tif (outcome.ok) log.info(written(fields));\n\t\t\t},\n\t\t);\n\t};\n}\n\n/**\n * The same `permissions()` instance, traced: a span per `can` — its subject,\n * permission, object and whether it was allowed — and per `list`, and a\n * `janus.tuple.granted` or `janus.tuple.revoked` event for every tuple\n * written, the audit trail of who was given what.\n *\n * ```ts\n * const access = instrumentPermissions(permissions({ model, store }));\n * ```\n *\n * A denial is an answer, not a failure: `janus.allowed` is `false` and the\n * span is `ok`. A relation store that cannot answer fails the span.\n */\nexport function instrumentPermissions<A extends PermissionsLike>(access: A): A {\n\t// `permissions()` answers a frozen object, which a Proxy may not answer\n\t// differently for: the traced methods go on a copy, frozen in turn.\n\tconst copy: Record<string, unknown> = Object.fromEntries(\n\t\tObject.entries(access),\n\t);\n\tconst userTypes = new Set(access.model?.subjects ?? []);\n\tfor (const [key, tracer] of Object.entries(tracersFor(userTypes))) {\n\t\tconst method: unknown = copy[key];\n\t\tif (typeof method !== 'function') continue;\n\t\tcopy[key] = tracer((...args) =>\n\t\t\tPromise.resolve(method.apply(access, args)),\n\t\t);\n\t}\n\treturn Object.freeze(copy) as A;\n}\n"
|
|
12
12
|
],
|
|
13
|
-
"mappings": "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",
|
|
14
|
-
"debugId": "
|
|
13
|
+
"mappings": "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",
|
|
14
|
+
"debugId": "F208819435F0AAFC64756E2164756E21",
|
|
15
15
|
"names": []
|
|
16
16
|
}
|
package/docs/guide/tracing.md
CHANGED
|
@@ -337,6 +337,20 @@ as after a password. Nothing is written for the mail: it sends none.
|
|
|
337
337
|
// name = 'janus.signIn' and janus.signIn.proven = true, grouped by user.id — who joined without a credential
|
|
338
338
|
```
|
|
339
339
|
|
|
340
|
+
Accepting an invitation first proves the address with
|
|
341
|
+
`verifyEmail.proveFirst`, which drops whatever somebody who signed up with
|
|
342
|
+
it left there — a password, a second factor, sessions. When it proved, it
|
|
343
|
+
writes `janus.email.verified`, marked; an e-mail already proved writes
|
|
344
|
+
nothing. Never the address:
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
POST /invitation/accept server
|
|
348
|
+
├─ janus.verifyEmail.proveFirst janus.user.type=user user.id=0199…
|
|
349
|
+
│ log janus.email.verified user.id=0199… janus.email.proveFirst=true
|
|
350
|
+
└─ janus.signInProven janus.user.type=user user.id=0199… janus.signIn.status=signedIn
|
|
351
|
+
log janus.signIn user.id=0199… janus.signIn.proven=true
|
|
352
|
+
```
|
|
353
|
+
|
|
340
354
|
## A step-up
|
|
341
355
|
|
|
342
356
|
A step-up — a signed-in user proving again who they are before a
|
package/docs/roadmap.md
CHANGED
|
@@ -33,6 +33,11 @@ Nothing yet.
|
|
|
33
33
|
|
|
34
34
|
Newest first; the [CHANGELOG](../CHANGELOG.md) holds every release.
|
|
35
35
|
|
|
36
|
+
- **An e-mail proved on the application's proof, traced, v0.11.0** —
|
|
37
|
+
`verifyEmail.proveFirst` is a span, `janus.<type>.verifyEmail.proveFirst`,
|
|
38
|
+
with the `user.id` it proved, and writes `janus.email.verified` marked
|
|
39
|
+
`janus.email.proveFirst: true` when it proved — nothing for an e-mail
|
|
40
|
+
already proved, and never the address. Needs `@nxgt/janus` 0.22.0.
|
|
36
41
|
- **A sign-in on the application's proof, traced, v0.10.0** —
|
|
37
42
|
`signInProven` is a span, `janus.<type>.signInProven`, with
|
|
38
43
|
`janus.signIn.status`, and writes `janus.signIn`, `janus.signIn.refused` or
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/janus-telemetry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Observability for @nxgt/janus on @nxgt/telemetry: a span per flow and per permission check, and the security events worth an audit trail — never a login, an e-mail, a password, a session token, a one-time token or a session id",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,13 +49,13 @@
|
|
|
49
49
|
]
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@nxgt/janus": "^0.
|
|
52
|
+
"@nxgt/janus": "^0.22.0",
|
|
53
53
|
"@nxgt/telemetry": "0.2.1",
|
|
54
54
|
"@types/bun": "^1.4.2",
|
|
55
55
|
"zod": "^4.6.5"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@nxgt/janus": "^0.
|
|
58
|
+
"@nxgt/janus": "^0.22.0",
|
|
59
59
|
"@nxgt/telemetry": ">=0.2.1 <1",
|
|
60
60
|
"typescript": "^6.0.3"
|
|
61
61
|
}
|