@atlasauth/emulator-core 0.1.0 → 0.3.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/dist/adopt.d.ts +50 -0
- package/dist/adopt.js +57 -0
- package/dist/adopt.js.map +1 -0
- package/dist/coverage.d.ts +15 -0
- package/dist/coverage.js +31 -0
- package/dist/coverage.js.map +1 -0
- package/dist/crypto-util.d.ts +10 -0
- package/dist/crypto-util.js +76 -0
- package/dist/crypto-util.js.map +1 -0
- package/dist/custom-html.d.ts +57 -0
- package/dist/custom-html.js +491 -0
- package/dist/custom-html.js.map +1 -0
- package/dist/engine.d.ts +34 -3
- package/dist/engine.js +57 -8
- package/dist/engine.js.map +1 -1
- package/dist/error-catalog.js +16 -0
- package/dist/error-catalog.js.map +1 -1
- package/dist/event-gate.d.ts +3 -0
- package/dist/event-gate.js +430 -0
- package/dist/event-gate.js.map +1 -0
- package/dist/generic.js +14 -2
- package/dist/generic.js.map +1 -1
- package/dist/handlers/access-signals.d.ts +48 -0
- package/dist/handlers/access-signals.js +76 -0
- package/dist/handlers/access-signals.js.map +1 -0
- package/dist/handlers/approvals.d.ts +2 -0
- package/dist/handlers/approvals.js +418 -0
- package/dist/handlers/approvals.js.map +1 -0
- package/dist/handlers/authz-data.d.ts +2 -0
- package/dist/handlers/authz-data.js +627 -0
- package/dist/handlers/authz-data.js.map +1 -0
- package/dist/handlers/authz-layers.d.ts +229 -0
- package/dist/handlers/authz-layers.js +786 -0
- package/dist/handlers/authz-layers.js.map +1 -0
- package/dist/handlers/authz-state.d.ts +80 -0
- package/dist/handlers/authz-state.js +175 -0
- package/dist/handlers/authz-state.js.map +1 -0
- package/dist/handlers/authz.d.ts +2 -0
- package/dist/handlers/authz.js +410 -0
- package/dist/handlers/authz.js.map +1 -0
- package/dist/handlers/billing.d.ts +100 -0
- package/dist/handlers/billing.js +877 -0
- package/dist/handlers/billing.js.map +1 -0
- package/dist/handlers/cedar-ext.d.ts +35 -0
- package/dist/handlers/cedar-ext.js +174 -0
- package/dist/handlers/cedar-ext.js.map +1 -0
- package/dist/handlers/cedar.d.ts +146 -0
- package/dist/handlers/cedar.js +689 -0
- package/dist/handlers/cedar.js.map +1 -0
- package/dist/handlers/connections.d.ts +5 -0
- package/dist/handlers/connections.js +561 -0
- package/dist/handlers/connections.js.map +1 -0
- package/dist/handlers/control.js +6 -1
- package/dist/handlers/control.js.map +1 -1
- package/dist/handlers/device.d.ts +47 -0
- package/dist/handlers/device.js +665 -0
- package/dist/handlers/device.js.map +1 -0
- package/dist/handlers/emu3-misc.d.ts +38 -0
- package/dist/handlers/emu3-misc.js +1056 -0
- package/dist/handlers/emu3-misc.js.map +1 -0
- package/dist/handlers/emu4-actions-access.d.ts +46 -0
- package/dist/handlers/emu4-actions-access.js +107 -0
- package/dist/handlers/emu4-actions-access.js.map +1 -0
- package/dist/handlers/emu4-actions-catalog-extra.d.ts +3 -0
- package/dist/handlers/emu4-actions-catalog-extra.js +204 -0
- package/dist/handlers/emu4-actions-catalog-extra.js.map +1 -0
- package/dist/handlers/emu4-actions-catalog.d.ts +3 -0
- package/dist/handlers/emu4-actions-catalog.js +143 -0
- package/dist/handlers/emu4-actions-catalog.js.map +1 -0
- package/dist/handlers/emu4-actions-def.d.ts +50 -0
- package/dist/handlers/emu4-actions-def.js +250 -0
- package/dist/handlers/emu4-actions-def.js.map +1 -0
- package/dist/handlers/emu4-actions-sandbox.d.ts +36 -0
- package/dist/handlers/emu4-actions-sandbox.js +318 -0
- package/dist/handlers/emu4-actions-sandbox.js.map +1 -0
- package/dist/handlers/emu4-actions-typegen.d.ts +5 -0
- package/dist/handlers/emu4-actions-typegen.js +73 -0
- package/dist/handlers/emu4-actions-typegen.js.map +1 -0
- package/dist/handlers/emu4-actions.d.ts +2 -0
- package/dist/handlers/emu4-actions.js +506 -0
- package/dist/handlers/emu4-actions.js.map +1 -0
- package/dist/handlers/emu4-authz-trust.d.ts +40 -0
- package/dist/handlers/emu4-authz-trust.js +488 -0
- package/dist/handlers/emu4-authz-trust.js.map +1 -0
- package/dist/handlers/emu4-authz.d.ts +2 -0
- package/dist/handlers/emu4-authz.js +752 -0
- package/dist/handlers/emu4-authz.js.map +1 -0
- package/dist/handlers/emu4-billing-core.d.ts +23 -0
- package/dist/handlers/emu4-billing-core.js +22 -0
- package/dist/handlers/emu4-billing-core.js.map +1 -0
- package/dist/handlers/emu4-billing-x.d.ts +2 -0
- package/dist/handlers/emu4-billing-x.js +489 -0
- package/dist/handlers/emu4-billing-x.js.map +1 -0
- package/dist/handlers/emu4-billing.d.ts +14 -0
- package/dist/handlers/emu4-billing.js +846 -0
- package/dist/handlers/emu4-billing.js.map +1 -0
- package/dist/handlers/emu4-clones.d.ts +2 -0
- package/dist/handlers/emu4-clones.js +322 -0
- package/dist/handlers/emu4-clones.js.map +1 -0
- package/dist/handlers/emu4-compliance.d.ts +8 -0
- package/dist/handlers/emu4-compliance.js +39 -0
- package/dist/handlers/emu4-compliance.js.map +1 -0
- package/dist/handlers/emu4-config.d.ts +14 -0
- package/dist/handlers/emu4-config.js +148 -0
- package/dist/handlers/emu4-config.js.map +1 -0
- package/dist/handlers/emu4-cookies.d.ts +8 -0
- package/dist/handlers/emu4-cookies.js +248 -0
- package/dist/handlers/emu4-cookies.js.map +1 -0
- package/dist/handlers/emu4-erasure.d.ts +2 -0
- package/dist/handlers/emu4-erasure.js +587 -0
- package/dist/handlers/emu4-erasure.js.map +1 -0
- package/dist/handlers/emu4-federation.d.ts +8 -0
- package/dist/handlers/emu4-federation.js +18 -0
- package/dist/handlers/emu4-federation.js.map +1 -0
- package/dist/handlers/emu4-journey-math.d.ts +42 -0
- package/dist/handlers/emu4-journey-math.js +99 -0
- package/dist/handlers/emu4-journey-math.js.map +1 -0
- package/dist/handlers/emu4-messaging.d.ts +21 -0
- package/dist/handlers/emu4-messaging.js +595 -0
- package/dist/handlers/emu4-messaging.js.map +1 -0
- package/dist/handlers/emu4-minors.d.ts +7 -0
- package/dist/handlers/emu4-minors.js +408 -0
- package/dist/handlers/emu4-minors.js.map +1 -0
- package/dist/handlers/emu4-oauth-audit.d.ts +5 -0
- package/dist/handlers/emu4-oauth-audit.js +17 -0
- package/dist/handlers/emu4-oauth-audit.js.map +1 -0
- package/dist/handlers/emu4-oauth-auth.d.ts +83 -0
- package/dist/handlers/emu4-oauth-auth.js +363 -0
- package/dist/handlers/emu4-oauth-auth.js.map +1 -0
- package/dist/handlers/emu4-oauth-delivery.d.ts +68 -0
- package/dist/handlers/emu4-oauth-delivery.js +207 -0
- package/dist/handlers/emu4-oauth-delivery.js.map +1 -0
- package/dist/handlers/emu4-oauth-keys.d.ts +11 -0
- package/dist/handlers/emu4-oauth-keys.js +268 -0
- package/dist/handlers/emu4-oauth-keys.js.map +1 -0
- package/dist/handlers/emu4-oauth-pub.d.ts +36 -0
- package/dist/handlers/emu4-oauth-pub.js +420 -0
- package/dist/handlers/emu4-oauth-pub.js.map +1 -0
- package/dist/handlers/emu4-oauth.d.ts +10 -0
- package/dist/handlers/emu4-oauth.js +23 -0
- package/dist/handlers/emu4-oauth.js.map +1 -0
- package/dist/handlers/emu4-policies.d.ts +2 -0
- package/dist/handlers/emu4-policies.js +408 -0
- package/dist/handlers/emu4-policies.js.map +1 -0
- package/dist/handlers/emu4-region.d.ts +2 -0
- package/dist/handlers/emu4-region.js +189 -0
- package/dist/handlers/emu4-region.js.map +1 -0
- package/dist/handlers/emu4-saml.d.ts +12 -0
- package/dist/handlers/emu4-saml.js +532 -0
- package/dist/handlers/emu4-saml.js.map +1 -0
- package/dist/handlers/emu4-shared.d.ts +44 -0
- package/dist/handlers/emu4-shared.js +90 -0
- package/dist/handlers/emu4-shared.js.map +1 -0
- package/dist/handlers/emu4-snapshots.d.ts +38 -0
- package/dist/handlers/emu4-snapshots.js +231 -0
- package/dist/handlers/emu4-snapshots.js.map +1 -0
- package/dist/handlers/emu4-sns.d.ts +9 -0
- package/dist/handlers/emu4-sns.js +21 -0
- package/dist/handlers/emu4-sns.js.map +1 -0
- package/dist/handlers/emu4-trust-binding.d.ts +27 -0
- package/dist/handlers/emu4-trust-binding.js +344 -0
- package/dist/handlers/emu4-trust-binding.js.map +1 -0
- package/dist/handlers/emu4-trust.d.ts +35 -0
- package/dist/handlers/emu4-trust.js +543 -0
- package/dist/handlers/emu4-trust.js.map +1 -0
- package/dist/handlers/federation.d.ts +2 -0
- package/dist/handlers/federation.js +481 -0
- package/dist/handlers/federation.js.map +1 -0
- package/dist/handlers/fga-engine.d.ts +78 -0
- package/dist/handlers/fga-engine.js +663 -0
- package/dist/handlers/fga-engine.js.map +1 -0
- package/dist/handlers/governance.d.ts +2 -0
- package/dist/handlers/governance.js +460 -0
- package/dist/handlers/governance.js.map +1 -0
- package/dist/handlers/hooks.js +17 -1
- package/dist/handlers/hooks.js.map +1 -1
- package/dist/handlers/index.d.ts +5 -1
- package/dist/handlers/index.js +45 -3
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/keys.js +6 -1
- package/dist/handlers/keys.js.map +1 -1
- package/dist/handlers/machines.js +61 -8
- package/dist/handlers/machines.js.map +1 -1
- package/dist/handlers/messaging.d.ts +6 -0
- package/dist/handlers/messaging.js +893 -0
- package/dist/handlers/messaging.js.map +1 -0
- package/dist/handlers/oauth-adv.d.ts +191 -0
- package/dist/handlers/oauth-adv.js +1305 -0
- package/dist/handlers/oauth-adv.js.map +1 -0
- package/dist/handlers/oauth-flows.d.ts +52 -0
- package/dist/handlers/oauth-flows.js +480 -0
- package/dist/handlers/oauth-flows.js.map +1 -0
- package/dist/handlers/oauth.d.ts +96 -0
- package/dist/handlers/oauth.js +793 -0
- package/dist/handlers/oauth.js.map +1 -0
- package/dist/handlers/orgs.js +6 -0
- package/dist/handlers/orgs.js.map +1 -1
- package/dist/handlers/passkeys.d.ts +3 -0
- package/dist/handlers/passkeys.js +293 -0
- package/dist/handlers/passkeys.js.map +1 -0
- package/dist/handlers/platform.d.ts +20 -0
- package/dist/handlers/platform.js +472 -0
- package/dist/handlers/platform.js.map +1 -0
- package/dist/handlers/round2.d.ts +8 -0
- package/dist/handlers/round2.js +372 -0
- package/dist/handlers/round2.js.map +1 -0
- package/dist/handlers/scim.d.ts +4 -0
- package/dist/handlers/scim.js +595 -0
- package/dist/handlers/scim.js.map +1 -0
- package/dist/handlers/sessions.d.ts +9 -3
- package/dist/handlers/sessions.js +76 -38
- package/dist/handlers/sessions.js.map +1 -1
- package/dist/handlers/support.d.ts +20 -0
- package/dist/handlers/support.js +62 -0
- package/dist/handlers/support.js.map +1 -0
- package/dist/handlers/users.js +7 -0
- package/dist/handlers/users.js.map +1 -1
- package/dist/handlers/workflows.d.ts +2 -0
- package/dist/handlers/workflows.js +428 -0
- package/dist/handlers/workflows.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/dist/jwe.d.ts +18 -0
- package/dist/jwe.js +101 -0
- package/dist/jwe.js.map +1 -0
- package/dist/jws.d.ts +41 -0
- package/dist/jws.js +135 -0
- package/dist/jws.js.map +1 -0
- package/dist/messages.d.ts +7 -0
- package/dist/messages.js +8 -4
- package/dist/messages.js.map +1 -1
- package/dist/messaging-callbacks.d.ts +100 -0
- package/dist/messaging-callbacks.js +767 -0
- package/dist/messaging-callbacks.js.map +1 -0
- package/dist/openapi.js +41 -1
- package/dist/openapi.js.map +1 -1
- package/dist/parity-bin.js +3 -1
- package/dist/parity-bin.js.map +1 -1
- package/dist/parity-emu3-authz.d.ts +3 -0
- package/dist/parity-emu3-authz.js +61 -0
- package/dist/parity-emu3-authz.js.map +1 -0
- package/dist/parity-emu3-billing.d.ts +3 -0
- package/dist/parity-emu3-billing.js +25 -0
- package/dist/parity-emu3-billing.js.map +1 -0
- package/dist/parity-emu3-messaging.d.ts +3 -0
- package/dist/parity-emu3-messaging.js +27 -0
- package/dist/parity-emu3-messaging.js.map +1 -0
- package/dist/parity-emu3-misc.d.ts +2 -0
- package/dist/parity-emu3-misc.js +63 -0
- package/dist/parity-emu3-misc.js.map +1 -0
- package/dist/parity-emu3-oauth.d.ts +2 -0
- package/dist/parity-emu3-oauth.js +39 -0
- package/dist/parity-emu3-oauth.js.map +1 -0
- package/dist/parity-emu4-actions.d.ts +2 -0
- package/dist/parity-emu4-actions.js +38 -0
- package/dist/parity-emu4-actions.js.map +1 -0
- package/dist/parity-emu4-authz.d.ts +3 -0
- package/dist/parity-emu4-authz.js +68 -0
- package/dist/parity-emu4-authz.js.map +1 -0
- package/dist/parity-emu4-billing.d.ts +6 -0
- package/dist/parity-emu4-billing.js +44 -0
- package/dist/parity-emu4-billing.js.map +1 -0
- package/dist/parity-emu4-compliance.d.ts +2 -0
- package/dist/parity-emu4-compliance.js +92 -0
- package/dist/parity-emu4-compliance.js.map +1 -0
- package/dist/parity-emu4-federation.d.ts +2 -0
- package/dist/parity-emu4-federation.js +33 -0
- package/dist/parity-emu4-federation.js.map +1 -0
- package/dist/parity-emu4-messaging.d.ts +3 -0
- package/dist/parity-emu4-messaging.js +42 -0
- package/dist/parity-emu4-messaging.js.map +1 -0
- package/dist/parity-emu4-oauth.d.ts +2 -0
- package/dist/parity-emu4-oauth.js +55 -0
- package/dist/parity-emu4-oauth.js.map +1 -0
- package/dist/parity-emu4-trust.d.ts +2 -0
- package/dist/parity-emu4-trust.js +41 -0
- package/dist/parity-emu4-trust.js.map +1 -0
- package/dist/parity-routes.d.ts +14 -0
- package/dist/parity-routes.js +439 -0
- package/dist/parity-routes.js.map +1 -0
- package/dist/parity.d.ts +10 -3
- package/dist/parity.js +14 -5
- package/dist/parity.js.map +1 -1
- package/dist/sns-cert.d.ts +9 -0
- package/dist/sns-cert.js +101 -0
- package/dist/sns-cert.js.map +1 -0
- package/dist/tokens.d.ts +85 -3
- package/dist/tokens.js +196 -24
- package/dist/tokens.js.map +1 -1
- package/dist/webauthn-virtual.d.ts +70 -0
- package/dist/webauthn-virtual.js +186 -0
- package/dist/webauthn-virtual.js.map +1 -0
- package/dist/webhook-ext.d.ts +16 -0
- package/dist/webhook-ext.js +218 -0
- package/dist/webhook-ext.js.map +1 -0
- package/dist/webhooks.d.ts +3 -0
- package/dist/webhooks.js +37 -3
- package/dist/webhooks.js.map +1 -1
- package/package.json +2 -2
package/dist/adopt.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Engine } from './engine';
|
|
2
|
+
import type { Obj } from './openapi';
|
|
3
|
+
/**
|
|
4
|
+
* Put a record that already exists elsewhere (another store sharing this engine's state, such as the Frontend API mock)
|
|
5
|
+
* into the engine under its own id, with the same change-feed and webhook entries a create would make. Idempotent: an id
|
|
6
|
+
* already present is returned untouched. This is how `@atlasauth/emulator` keeps one state across its two surfaces.
|
|
7
|
+
*/
|
|
8
|
+
export interface AdoptUser {
|
|
9
|
+
id: string;
|
|
10
|
+
emails: Array<{
|
|
11
|
+
id: string;
|
|
12
|
+
email_address: string;
|
|
13
|
+
verified: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
primary_email_address_id: string | null;
|
|
16
|
+
first_name?: string | null;
|
|
17
|
+
last_name?: string | null;
|
|
18
|
+
username?: string | null;
|
|
19
|
+
external_id?: string | null;
|
|
20
|
+
image_url?: string | null;
|
|
21
|
+
password?: string | null;
|
|
22
|
+
public_metadata?: Obj;
|
|
23
|
+
private_metadata?: Obj;
|
|
24
|
+
unsafe_metadata?: Obj;
|
|
25
|
+
banned?: boolean;
|
|
26
|
+
created_at: number;
|
|
27
|
+
updated_at: number;
|
|
28
|
+
}
|
|
29
|
+
export declare function adoptUser(e: Engine, u: AdoptUser): Obj;
|
|
30
|
+
export declare function adoptOrganization(e: Engine, o: {
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
slug: string | null;
|
|
34
|
+
created_by?: string | null;
|
|
35
|
+
public_metadata?: Obj;
|
|
36
|
+
created_at: number;
|
|
37
|
+
updated_at: number;
|
|
38
|
+
}): Obj;
|
|
39
|
+
export declare function adoptMembership(e: Engine, orgId: string, userId: string, role: string): Obj;
|
|
40
|
+
/** A session minted elsewhere: it gets a row under its id, and `refreshToken` becomes a live refresh credential on the real route. */
|
|
41
|
+
export declare function adoptSession(e: Engine, s: {
|
|
42
|
+
id: string;
|
|
43
|
+
userId: string;
|
|
44
|
+
organizationId?: string | null;
|
|
45
|
+
refreshToken: string;
|
|
46
|
+
createdAt: number;
|
|
47
|
+
expiresAt: number;
|
|
48
|
+
lastActiveAt: number;
|
|
49
|
+
status: 'active' | 'revoked' | 'ended';
|
|
50
|
+
}): Obj;
|
package/dist/adopt.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.adoptUser = adoptUser;
|
|
4
|
+
exports.adoptOrganization = adoptOrganization;
|
|
5
|
+
exports.adoptMembership = adoptMembership;
|
|
6
|
+
exports.adoptSession = adoptSession;
|
|
7
|
+
const orgs_1 = require("./handlers/orgs");
|
|
8
|
+
const sessions_1 = require("./handlers/sessions");
|
|
9
|
+
const users_1 = require("./handlers/users");
|
|
10
|
+
function adoptUser(e, u) {
|
|
11
|
+
const have = e.db.users.get(u.id);
|
|
12
|
+
if (have)
|
|
13
|
+
return have;
|
|
14
|
+
const row = e.db.users.insert({
|
|
15
|
+
id: u.id,
|
|
16
|
+
username: u.username ?? null,
|
|
17
|
+
first_name: u.first_name ?? null,
|
|
18
|
+
last_name: u.last_name ?? null,
|
|
19
|
+
image_url: u.image_url ?? null,
|
|
20
|
+
external_id: u.external_id ?? null,
|
|
21
|
+
emails: u.emails,
|
|
22
|
+
primary_email_address_id: u.primary_email_address_id,
|
|
23
|
+
has_password: typeof u.password === 'string',
|
|
24
|
+
password_plain: u.password ?? null,
|
|
25
|
+
public_metadata: u.public_metadata ?? {},
|
|
26
|
+
unsafe_metadata: u.unsafe_metadata ?? {},
|
|
27
|
+
private_metadata: u.private_metadata ?? {},
|
|
28
|
+
banned: u.banned === true,
|
|
29
|
+
locked: false,
|
|
30
|
+
created_at: u.created_at,
|
|
31
|
+
updated_at: u.updated_at,
|
|
32
|
+
version: 1,
|
|
33
|
+
});
|
|
34
|
+
e.changed({ type: 'user.created', data: (0, users_1.presentUser)(e, row), resource: 'user', id: row.id, op: 'create' });
|
|
35
|
+
return row;
|
|
36
|
+
}
|
|
37
|
+
function adoptOrganization(e, o) {
|
|
38
|
+
const have = e.db.organizations.get(o.id);
|
|
39
|
+
if (have)
|
|
40
|
+
return have;
|
|
41
|
+
const row = e.db.organizations.insert({ id: o.id, name: o.name, slug: o.slug ?? o.id, image_url: null, public_metadata: o.public_metadata ?? {}, private_metadata: {}, created_by: o.created_by ?? null, created_at: o.created_at, updated_at: o.updated_at, version: 1 });
|
|
42
|
+
e.changed({ type: 'organization.created', data: (0, orgs_1.presentOrg)(e, row), resource: 'organization', id: row.id, op: 'create' });
|
|
43
|
+
return row;
|
|
44
|
+
}
|
|
45
|
+
function adoptMembership(e, orgId, userId, role) {
|
|
46
|
+
return e.db.memberships.find((m) => m.organization_id === orgId && m.user_id === userId) ?? (0, orgs_1.addMember)(e, orgId, userId, role);
|
|
47
|
+
}
|
|
48
|
+
/** A session minted elsewhere: it gets a row under its id, and `refreshToken` becomes a live refresh credential on the real route. */
|
|
49
|
+
function adoptSession(e, s) {
|
|
50
|
+
const have = e.db.sessions.get(s.id);
|
|
51
|
+
if (have)
|
|
52
|
+
return have;
|
|
53
|
+
const row = e.db.sessions.insert({ id: s.id, user_id: s.userId, organization_id: s.organizationId ?? null, status: s.status === 'active' ? 'active' : 'revoked', created_at: s.createdAt, expires_at: s.expiresAt, last_active_at: s.lastActiveAt });
|
|
54
|
+
(0, sessions_1.issueRefreshToken)(e, s.id, s.refreshToken);
|
|
55
|
+
return row;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=adopt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt.js","sourceRoot":"","sources":["../src/adopt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Engine } from './engine';
|
|
2
|
+
import type { Obj } from './openapi';
|
|
3
|
+
export type Coverage = 'handler' | 'generic';
|
|
4
|
+
/**
|
|
5
|
+
* What the emulator does for each operation of the OpenAPI document, for the surface-completeness matrix:
|
|
6
|
+
* `handler` = hand-written behaviour (state, side effects, events), `generic` = document-driven CRUD only (a valid answer,
|
|
7
|
+
* no side effects). Routes the engine serves that the document does not list (`/oauth2/*`, `/scim/v2/*`, the well-known
|
|
8
|
+
* documents) come back under `extra`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function coverageList(engine: Engine): {
|
|
11
|
+
operations: Record<string, Coverage>;
|
|
12
|
+
extra: string[];
|
|
13
|
+
};
|
|
14
|
+
/** Copy of the document with `x-atlas-emulator-coverage` set on every operation. */
|
|
15
|
+
export declare function annotateCoverage(doc: Obj, engine: Engine): Obj;
|
package/dist/coverage.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.coverageList = coverageList;
|
|
4
|
+
exports.annotateCoverage = annotateCoverage;
|
|
5
|
+
/**
|
|
6
|
+
* What the emulator does for each operation of the OpenAPI document, for the surface-completeness matrix:
|
|
7
|
+
* `handler` = hand-written behaviour (state, side effects, events), `generic` = document-driven CRUD only (a valid answer,
|
|
8
|
+
* no side effects). Routes the engine serves that the document does not list (`/oauth2/*`, `/scim/v2/*`, the well-known
|
|
9
|
+
* documents) come back under `extra`.
|
|
10
|
+
*/
|
|
11
|
+
function coverageList(engine) {
|
|
12
|
+
const documented = new Set(engine.index.ops.map((o) => `${o.method} ${o.path}`));
|
|
13
|
+
return {
|
|
14
|
+
operations: engine.coverage(),
|
|
15
|
+
extra: engine.handwritten().filter((r) => !r.op && !r.pattern.startsWith('/__emulator')).map((r) => `${r.method} ${r.pattern}`).filter((k) => !documented.has(k)),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Copy of the document with `x-atlas-emulator-coverage` set on every operation. */
|
|
19
|
+
function annotateCoverage(doc, engine) {
|
|
20
|
+
const cov = engine.coverage();
|
|
21
|
+
const out = structuredClone(doc);
|
|
22
|
+
for (const [path, item] of Object.entries(out.paths ?? {})) {
|
|
23
|
+
for (const method of Object.keys(item)) {
|
|
24
|
+
const level = cov[`${method.toUpperCase()} ${path}`];
|
|
25
|
+
if (level)
|
|
26
|
+
item[method]['x-atlas-emulator-coverage'] = level;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":";;AAWA,oCAMC;AAGD,4CAUC;AAzBD;;;;;GAKG;AACH,SAAgB,YAAY,CAAC,MAAc;IACzC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACjF,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE;QAC7B,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAClK,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,SAAgB,gBAAgB,CAAC,GAAQ,EAAE,MAAc;IACvD,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QAChE,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;YACrD,IAAI,KAAK;gBAAE,IAAI,CAAC,MAAM,CAAC,CAAC,2BAA2B,CAAC,GAAG,KAAK,CAAC;QAC/D,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const bytesToB64url: (bytes: Uint8Array) => string;
|
|
2
|
+
export declare const sha256: (data: string | Uint8Array) => Promise<Uint8Array>;
|
|
3
|
+
/** Whether `pem` is a public key of a type a device may enrol with (Ed25519, ECDSA P-256, RSA). */
|
|
4
|
+
export declare const isDeviceKey: (pem: string) => Promise<boolean>;
|
|
5
|
+
/** RFC 7638 thumbprint of an SPKI PEM, base64url, or null for a key this engine cannot read. */
|
|
6
|
+
export declare function jwkThumbprint(pem: string): Promise<string | null>;
|
|
7
|
+
/** Verify a device's signature over the raw challenge string, the way the real route does (EC signatures are r||s). Never throws. */
|
|
8
|
+
export declare function verifyDeviceSignature(pem: string, challenge: string, signatureB64url: string): Promise<boolean>;
|
|
9
|
+
/** PKCE S256 challenge for a verifier. */
|
|
10
|
+
export declare const pkceChallenge: (verifier: string) => Promise<string>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pkceChallenge = exports.isDeviceKey = exports.sha256 = exports.bytesToB64url = void 0;
|
|
4
|
+
exports.jwkThumbprint = jwkThumbprint;
|
|
5
|
+
exports.verifyDeviceSignature = verifyDeviceSignature;
|
|
6
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
+
/** Web Crypto helpers (portable: no node:crypto, so the engine still runs in a browser worker). */
|
|
8
|
+
const b64urlToBytes = (s) => {
|
|
9
|
+
const pad = s.replace(/-/g, '+').replace(/_/g, '/');
|
|
10
|
+
return Uint8Array.from(atob(pad + '='.repeat((4 - (pad.length % 4)) % 4)), (c) => c.charCodeAt(0));
|
|
11
|
+
};
|
|
12
|
+
const bytesToB64url = (bytes) => {
|
|
13
|
+
let s = '';
|
|
14
|
+
for (const b of bytes)
|
|
15
|
+
s += String.fromCharCode(b);
|
|
16
|
+
return btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
17
|
+
};
|
|
18
|
+
exports.bytesToB64url = bytesToB64url;
|
|
19
|
+
const enc = new TextEncoder();
|
|
20
|
+
const sha256 = async (data) => new Uint8Array(await crypto.subtle.digest('SHA-256', (typeof data === 'string' ? enc.encode(data) : data)));
|
|
21
|
+
exports.sha256 = sha256;
|
|
22
|
+
const pemToDer = (pem) => {
|
|
23
|
+
const body = pem.replace(/-----[A-Z ]+-----/g, '').replace(/\s+/g, '');
|
|
24
|
+
return Uint8Array.from(atob(body), (c) => c.charCodeAt(0));
|
|
25
|
+
};
|
|
26
|
+
const KINDS = [
|
|
27
|
+
{ import: { name: 'Ed25519' }, verify: { name: 'Ed25519' }, jwkKeys: ['crv', 'kty', 'x'] },
|
|
28
|
+
{ import: { name: 'ECDSA', namedCurve: 'P-256' }, verify: { name: 'ECDSA', hash: 'SHA-256' }, jwkKeys: ['crv', 'kty', 'x', 'y'] },
|
|
29
|
+
{ import: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, verify: { name: 'RSASSA-PKCS1-v1_5' }, jwkKeys: ['e', 'kty', 'n'] },
|
|
30
|
+
];
|
|
31
|
+
async function importPublic(pem) {
|
|
32
|
+
let der;
|
|
33
|
+
try {
|
|
34
|
+
der = pemToDer(pem);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
for (const kind of KINDS) {
|
|
40
|
+
try {
|
|
41
|
+
return { key: await crypto.subtle.importKey('spki', der, kind.import, true, ['verify']), kind };
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
/* try the next key type */
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
/** Whether `pem` is a public key of a type a device may enrol with (Ed25519, ECDSA P-256, RSA). */
|
|
50
|
+
const isDeviceKey = async (pem) => (await importPublic(pem)) !== null;
|
|
51
|
+
exports.isDeviceKey = isDeviceKey;
|
|
52
|
+
/** RFC 7638 thumbprint of an SPKI PEM, base64url, or null for a key this engine cannot read. */
|
|
53
|
+
async function jwkThumbprint(pem) {
|
|
54
|
+
const k = await importPublic(pem);
|
|
55
|
+
if (!k)
|
|
56
|
+
return null;
|
|
57
|
+
const jwk = (await crypto.subtle.exportKey('jwk', k.key));
|
|
58
|
+
const canonical = JSON.stringify(Object.fromEntries(k.kind.jwkKeys.map((n) => [n, jwk[n]])));
|
|
59
|
+
return (0, exports.bytesToB64url)(await (0, exports.sha256)(canonical));
|
|
60
|
+
}
|
|
61
|
+
/** Verify a device's signature over the raw challenge string, the way the real route does (EC signatures are r||s). Never throws. */
|
|
62
|
+
async function verifyDeviceSignature(pem, challenge, signatureB64url) {
|
|
63
|
+
try {
|
|
64
|
+
const k = await importPublic(pem);
|
|
65
|
+
if (!k)
|
|
66
|
+
return false;
|
|
67
|
+
return await crypto.subtle.verify(k.kind.verify, k.key, b64urlToBytes(signatureB64url), enc.encode(challenge));
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** PKCE S256 challenge for a verifier. */
|
|
74
|
+
const pkceChallenge = async (verifier) => (0, exports.bytesToB64url)(await (0, exports.sha256)(verifier));
|
|
75
|
+
exports.pkceChallenge = pkceChallenge;
|
|
76
|
+
//# sourceMappingURL=crypto-util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-util.js","sourceRoot":"","sources":["../src/crypto-util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom hosted HTML and CSS for a page template region (the `custom` component).
|
|
3
|
+
*
|
|
4
|
+
* The author's markup is never trusted, and never placed in the sign-in page itself. Three layers, each enough on its own:
|
|
5
|
+
*
|
|
6
|
+
* 1. Allowlist sanitizer (this file). Only the tags, attributes and CSS properties below survive; there is no script, no style
|
|
7
|
+
* attribute, no event handler, no form control, no iframe, no object, no SVG, no `url()`, no import and no custom property.
|
|
8
|
+
* Links and images are https (links also mailto) only. A write that contains anything else is refused with the reason;
|
|
9
|
+
* the same function runs again, leniently (dropping what it does not allow), every time the template is rendered, so a
|
|
10
|
+
* row that was edited in the database is just as safe.
|
|
11
|
+
* 2. Server-side render into a sandboxed iframe (`srcdoc`): `sandbox` without `allow-scripts` or `allow-same-origin`, so the
|
|
12
|
+
* frame has an opaque origin and cannot touch the sign-in form, read its fields, restyle it, or draw over it.
|
|
13
|
+
* 3. A content-security-policy inside the frame that allows no script, no connection, no form post and no base element, and
|
|
14
|
+
* images from https only.
|
|
15
|
+
*
|
|
16
|
+
* Template variables are a fixed list substituted into text (never into attributes), HTML-escaped.
|
|
17
|
+
*
|
|
18
|
+
* This is the same allowlist, tokenizer and CSS rules the Atlas API applies (copied, not imported: the emulator has no dependency on the
|
|
19
|
+
* server packages), so a block that is refused here is refused in production for the same reason.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MAX_CUSTOM_HTML_BYTES: number;
|
|
22
|
+
export declare const MAX_CUSTOM_CSS_BYTES: number;
|
|
23
|
+
export declare const MAX_CUSTOM_TAGS = 300;
|
|
24
|
+
export declare const CUSTOM_MIN_HEIGHT = 40;
|
|
25
|
+
export declare const CUSTOM_MAX_HEIGHT = 1200;
|
|
26
|
+
/** The variables a custom block may use as `{{name}}` in text. */
|
|
27
|
+
export declare const CUSTOM_VARIABLES: readonly ["year", "locale"];
|
|
28
|
+
export type CustomVariables = Partial<Record<(typeof CUSTOM_VARIABLES)[number], string>>;
|
|
29
|
+
export interface Sanitized {
|
|
30
|
+
out: string;
|
|
31
|
+
/** What was not allowed. Empty means the input was already clean. */
|
|
32
|
+
problems: string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Reduce markup to the allowlist. Returns the clean markup and every problem found (a tag, attribute or value that was
|
|
36
|
+
* dropped). `vars` substitutes `{{year}}` / `{{locale}}` in text (escaped); an unknown `{{name}}` is a problem.
|
|
37
|
+
*/
|
|
38
|
+
export declare function sanitizeCustomHtml(input: string, opts?: {
|
|
39
|
+
vars?: CustomVariables;
|
|
40
|
+
}): Sanitized;
|
|
41
|
+
/** Reduce CSS to the allowlist: class/tag selectors, a fixed property list, no url(), no imports, no custom properties. */
|
|
42
|
+
export declare function sanitizeCustomCss(input: string): Sanitized;
|
|
43
|
+
/** The policy inside the frame: nothing runs, nothing connects, nothing posts; images from https only; no base element. */
|
|
44
|
+
export declare const CUSTOM_FRAME_CSP = "default-src 'none'; img-src https:; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'";
|
|
45
|
+
/** The `sandbox` attribute value: popups only (for links), and never scripts, forms or the page's origin. */
|
|
46
|
+
export declare const CUSTOM_FRAME_SANDBOX = "allow-popups allow-popups-to-escape-sandbox";
|
|
47
|
+
/** The complete document placed in the iframe. `html` and `css` must already be sanitized. */
|
|
48
|
+
export declare function customFrameDocument(html: string, css: string, lang: string): string;
|
|
49
|
+
/** The iframe element for a custom block (sanitizes again: the stored value is not trusted at render time). */
|
|
50
|
+
export declare function renderCustomBlock(n: {
|
|
51
|
+
html: string;
|
|
52
|
+
css?: string;
|
|
53
|
+
height: number;
|
|
54
|
+
title?: string;
|
|
55
|
+
}, vars?: CustomVariables): string;
|
|
56
|
+
/** The `custom` component of a page template, validated like the API does: the same refusals, the same messages, the stored value is the sanitized form. */
|
|
57
|
+
export declare function parseCustomComponent(n: Record<string, unknown>, path: string, depth: number): Record<string, unknown>;
|