@authhero/multi-tenancy 15.2.0 → 15.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/multi-tenancy.cjs +1 -1
  2. package/dist/multi-tenancy.mjs +2968 -1176
  3. package/dist/types/index.d.ts +5 -2
  4. package/dist/types/index.d.ts.map +1 -1
  5. package/dist/types/inheritance/legacy.d.ts.map +1 -1
  6. package/dist/types/inheritance/merge.d.ts +1 -0
  7. package/dist/types/inheritance/merge.d.ts.map +1 -1
  8. package/dist/types/inheritance/read.d.ts.map +1 -1
  9. package/dist/types/inheritance/report.d.ts +6 -2
  10. package/dist/types/inheritance/report.d.ts.map +1 -1
  11. package/dist/types/inheritance/types.d.ts +3 -1
  12. package/dist/types/inheritance/types.d.ts.map +1 -1
  13. package/dist/types/init.d.ts +84 -1
  14. package/dist/types/init.d.ts.map +1 -1
  15. package/dist/types/middleware/config-sync-mode.d.ts +39 -0
  16. package/dist/types/middleware/config-sync-mode.d.ts.map +1 -0
  17. package/dist/types/middleware/index.d.ts +3 -1
  18. package/dist/types/middleware/index.d.ts.map +1 -1
  19. package/dist/types/middleware/protect-synced.d.ts +1 -1
  20. package/dist/types/middleware/protect-synced.d.ts.map +1 -1
  21. package/dist/types/middleware/settings-inheritance.d.ts +20 -2
  22. package/dist/types/middleware/settings-inheritance.d.ts.map +1 -1
  23. package/dist/types/operations/detach.d.ts +85 -0
  24. package/dist/types/operations/detach.d.ts.map +1 -0
  25. package/dist/types/operations/enqueue.d.ts +8 -1
  26. package/dist/types/operations/enqueue.d.ts.map +1 -1
  27. package/dist/types/operations/index.d.ts +7 -1
  28. package/dist/types/operations/index.d.ts.map +1 -1
  29. package/dist/types/operations/recorder.d.ts +2 -0
  30. package/dist/types/operations/recorder.d.ts.map +1 -1
  31. package/dist/types/operations/sync-defaults.d.ts +58 -0
  32. package/dist/types/operations/sync-defaults.d.ts.map +1 -0
  33. package/dist/types/operations/tenant-members-request.d.ts +97 -0
  34. package/dist/types/operations/tenant-members-request.d.ts.map +1 -0
  35. package/dist/types/operations/types.d.ts +2 -0
  36. package/dist/types/operations/types.d.ts.map +1 -1
  37. package/dist/types/rollout/index.d.ts +2 -0
  38. package/dist/types/rollout/index.d.ts.map +1 -1
  39. package/dist/types/rollout/payload.d.ts +15 -0
  40. package/dist/types/rollout/payload.d.ts.map +1 -1
  41. package/dist/types/rollout/resolved-sync.d.ts +112 -0
  42. package/dist/types/rollout/resolved-sync.d.ts.map +1 -0
  43. package/dist/types/rollouts/advance.d.ts +44 -0
  44. package/dist/types/rollouts/advance.d.ts.map +1 -0
  45. package/dist/types/rollouts/config.d.ts +54 -0
  46. package/dist/types/rollouts/config.d.ts.map +1 -0
  47. package/dist/types/rollouts/controller.d.ts +29 -0
  48. package/dist/types/rollouts/controller.d.ts.map +1 -0
  49. package/dist/types/rollouts/enumerate.d.ts +25 -0
  50. package/dist/types/rollouts/enumerate.d.ts.map +1 -0
  51. package/dist/types/rollouts/hashes.d.ts +10 -0
  52. package/dist/types/rollouts/hashes.d.ts.map +1 -0
  53. package/dist/types/rollouts/index.d.ts +21 -0
  54. package/dist/types/rollouts/index.d.ts.map +1 -0
  55. package/dist/types/rollouts/plan.d.ts +29 -0
  56. package/dist/types/rollouts/plan.d.ts.map +1 -0
  57. package/dist/types/rollouts/reconcile.d.ts +38 -0
  58. package/dist/types/rollouts/reconcile.d.ts.map +1 -0
  59. package/dist/types/rollouts/status.d.ts +28 -0
  60. package/dist/types/rollouts/status.d.ts.map +1 -0
  61. package/dist/types/rollouts/trigger.d.ts +52 -0
  62. package/dist/types/rollouts/trigger.d.ts.map +1 -0
  63. package/dist/types/rollouts/types.d.ts +25 -0
  64. package/dist/types/rollouts/types.d.ts.map +1 -0
  65. package/dist/types/rollouts/verify.d.ts +50 -0
  66. package/dist/types/rollouts/verify.d.ts.map +1 -0
  67. package/dist/types/routes/tenants.d.ts.map +1 -1
  68. package/dist/types/types.d.ts +20 -0
  69. package/dist/types/types.d.ts.map +1 -1
  70. package/dist/types/utils/tenant-settings.d.ts +13 -0
  71. package/dist/types/utils/tenant-settings.d.ts.map +1 -0
  72. package/dist/types/utils/tenant-tree.d.ts +2 -1
  73. package/dist/types/utils/tenant-tree.d.ts.map +1 -1
  74. package/package.json +5 -5
@@ -0,0 +1,97 @@
1
+ import { type DataAdapters, type ExecuteTenantMemberRequestOptions, type TenantMemberRequest, type TenantMembersBackend, type TenantOperation } from "authhero";
2
+ import type { OperationRecorder } from "./recorder";
3
+ import type { TenantOperationExecutor, TenantOperationStores } from "./types";
4
+ /**
5
+ * The `tenant-members-request` tenant operation (issue #1550): carries out a
6
+ * team change that a tenant registered as a request in its own database.
7
+ *
8
+ * The request lives on the tenant's side, so the operation reaches it through
9
+ * a {@link TenantMemberRequestStore}: in-process for tenants that share the
10
+ * control plane's database, a dispatch push for tenants with their own. The
11
+ * operation's `input` is only `{ request_id }`: what was asked (addresses,
12
+ * ids) stays on the request row, because anyone who can read operations can
13
+ * read `input`.
14
+ */
15
+ /** How the control plane reads and answers a tenant's requests. */
16
+ export interface TenantMemberRequestStore {
17
+ get(tenantId: string, id: string): Promise<TenantMemberRequest | null>;
18
+ /**
19
+ * Writes the outcome, only while the request is still `pending`. Returns
20
+ * false when it was already finished, which makes a re-run harmless.
21
+ */
22
+ report(tenantId: string, id: string, outcome: {
23
+ status: "succeeded" | "failed";
24
+ result?: Record<string, unknown> | null;
25
+ error?: string | null;
26
+ }): Promise<boolean>;
27
+ /** Requests still `pending` and created before `olderThan` (ISO 8601). */
28
+ listPending(tenantId: string, options: {
29
+ olderThan: string;
30
+ }): Promise<TenantMemberRequest[]>;
31
+ }
32
+ /** For tenants whose database is the control plane's own. */
33
+ export declare function createInProcessMemberRequestStore(adapters: Pick<DataAdapters, "tenantMemberRequests">): TenantMemberRequestStore;
34
+ /** The request an operation is about, from its `input`. */
35
+ export declare function memberRequestIdOf(operation: Pick<TenantOperation, "input">): string | undefined;
36
+ export interface RunTenantMembersRequestParams {
37
+ operation: Pick<TenantOperation, "id" | "tenant_id" | "input">;
38
+ store: TenantMemberRequestStore;
39
+ /** The control-plane team backend, built without a request in hand. */
40
+ getBackend: () => TenantMembersBackend | Promise<TenantMembersBackend>;
41
+ recorder: Pick<OperationRecorder, "setResult">;
42
+ executeOptions?: ExecuteTenantMemberRequestOptions;
43
+ }
44
+ /**
45
+ * The step both executors run. Reads the request, carries it out against the
46
+ * tenant's team (which checks the tenant and the requester again), and writes
47
+ * the outcome back to the request.
48
+ *
49
+ * - A request that cannot or must not run (the requester left the team, the
50
+ * payload is wrong) is a legitimate outcome: the request is reported
51
+ * `failed` with the reason and the operation `succeeded`, because the
52
+ * control plane did its job. Nothing retries it.
53
+ * - Any other error (the database, the team backend, the write-back) fails the
54
+ * operation and leaves the request `pending`, so a later run or the
55
+ * reconcile sweep tries again. That is safe: the work is idempotent.
56
+ */
57
+ export declare function runTenantMembersRequestStep(params: RunTenantMembersRequestParams): Promise<Record<string, unknown>>;
58
+ /** How many failed runs a request gets before the sweep gives up on it. */
59
+ export declare const MAX_MEMBER_REQUEST_ATTEMPTS = 5;
60
+ /**
61
+ * Enqueues the operation for one request, once. A notification can arrive
62
+ * twice and the sweep can race it, so an operation that is already pending,
63
+ * running or succeeded for the request is returned instead of a new one.
64
+ */
65
+ export declare function enqueueTenantMemberRequest(deps: {
66
+ stores: TenantOperationStores;
67
+ executor: TenantOperationExecutor;
68
+ }, tenantId: string, requestId: string, options?: {
69
+ initiatedBy?: string;
70
+ }): Promise<TenantOperation>;
71
+ export interface ReconcileTenantMemberRequestsDeps {
72
+ stores: TenantOperationStores;
73
+ executor: TenantOperationExecutor;
74
+ store: TenantMemberRequestStore;
75
+ /** The tenants to look at, for example the ones with their own database. */
76
+ tenantIds: () => Promise<string[]> | string[];
77
+ /** Requests younger than this are left to the notification. Default 5 minutes. */
78
+ graceMs?: number;
79
+ maxAttempts?: number;
80
+ now?: () => Date;
81
+ }
82
+ export interface ReconcileTenantMemberRequestsResult {
83
+ checked: number;
84
+ enqueued: number;
85
+ gaveUp: number;
86
+ /** Tenants whose requests could not be read, for example an unreachable shard. */
87
+ unreachable: string[];
88
+ }
89
+ /**
90
+ * Sweep for requests the control plane never ran: the notification was lost,
91
+ * or the run failed. A tenant worker cannot run a cron, so this runs on the
92
+ * control plane. It enqueues the operation for a `pending` request that has
93
+ * none in flight, and after `maxAttempts` failed runs reports the request
94
+ * `failed` so it does not stay pending forever.
95
+ */
96
+ export declare function reconcileTenantMemberRequests(deps: ReconcileTenantMemberRequestsDeps): Promise<ReconcileTenantMemberRequestsResult>;
97
+ //# sourceMappingURL=tenant-members-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-members-request.d.ts","sourceRoot":"","sources":["../../../src/operations/tenant-members-request.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,8 @@ export interface EnqueueTenantOperationParams {
34
34
  initiated_by?: string;
35
35
  target_worker_version?: string;
36
36
  target_database_version?: string;
37
+ /** Kind-specific parameters, fixed at creation. Never contains secrets. */
38
+ input?: Record<string, unknown>;
37
39
  }
38
40
  /**
39
41
  * Executes an already-persisted operation row. Row-first contract: the
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/operations/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,4BAA4B,EAC5B,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,UAAU,CAAC;AAElB;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QACvB,OAAO,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,aAAa,CAAC;KACjD,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtD,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3E;AAED,mEAAmE;AACnE,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,uBAAuB,CAAC;IAC1C,qBAAqB,EAAE,4BAA4B,CAAC;CACrD;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,mBAAmB,CAAC;IAC1B,sDAAsD;IACtD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC;IACnD,KAAK,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,EAC3C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/operations/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,4BAA4B,EAC5B,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,UAAU,CAAC;AAElB;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QACvB,OAAO,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,aAAa,CAAC;KACjD,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtD,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3E;AAED,mEAAmE;AACnE,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,EAAE,uBAAuB,CAAC;IAC1C,qBAAqB,EAAE,4BAA4B,CAAC;CACrD;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,mBAAmB,CAAC;IAC1B,sDAAsD;IACtD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,sBAAsB,CAAC;IACnD,KAAK,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,EAC3C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -3,6 +3,8 @@ export type { DefaultsProjectionConfig, DefaultsProjectionEntities, DefaultsProj
3
3
  export { projectControlPlaneDefaults } from "./defaults-projection";
4
4
  export type { ControlPlaneDefaultsPayload, ControlPlaneDefaultsApplyResult, ControlPlaneTenantSeed, DefaultsPayloadEntities, } from "./payload";
5
5
  export { buildControlPlaneDefaultsPayload, applyControlPlaneDefaultsPayload, } from "./payload";
6
+ export type { ApplyResolvedBlockOptions, ApplyResolvedBlockResult, BuildResolvedBlockOptions, ResolvedConfigBlock, SyncEntity, SyncEntityOutcome, } from "./resolved-sync";
7
+ export { applyResolvedConfigBlock, buildResolvedConfigBlock, findUndecryptableKeyIds, syncedRowId, } from "./resolved-sync";
6
8
  /**
7
9
  * A control plane rollout applies the control plane's state to one or more
8
10
  * tenant databases. `syncDefaults` is the only operation today; schema
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rollout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EAEzB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAEpE,YAAY,EACV,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,gCAAgC,EAChC,gCAAgC,GACjC,MAAM,WAAW,CAAC;AAEnB;;;;;;;;;;GAUG;AACH,MAAM,WAAW,0BAA0B;IACzC,0EAA0E;IAC1E,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAExE;;;OAGG;IACH,qBAAqB,CACnB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,wBAAwB,GAC/B,0BAA0B,CAa5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rollout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EAEzB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAEpE,YAAY,EACV,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,gCAAgC,EAChC,gCAAgC,GACjC,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,yBAAyB,EACzB,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACnB,UAAU,EACV,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;GAUG;AACH,MAAM,WAAW,0BAA0B;IACzC,0EAA0E;IAC1E,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAExE;;;OAGG;IACH,qBAAqB,CACnB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,wBAAwB,GAC/B,0BAA0B,CAa5B"}
@@ -1,5 +1,6 @@
1
1
  import { DataAdapters, SigningKey } from "authhero";
2
2
  import { DefaultsProjectionEntities, DefaultsProjectionResult, EntityProjectionOutcome, ProjectableDefaults } from "./defaults-projection";
3
+ import { ApplyResolvedBlockOptions, ApplyResolvedBlockResult, ResolvedConfigBlock } from "./resolved-sync";
3
4
  /**
4
5
  * Entity flags for the wire payload — the six default entities plus signing
5
6
  * keys and tenant rows, which only flow through the payload (build + apply),
@@ -56,11 +57,18 @@ export interface ControlPlaneDefaultsPayload extends ProjectableDefaults {
56
57
  * {@link ControlPlaneTenantSeed}.
57
58
  */
58
59
  tenants: ControlPlaneTenantSeed[];
60
+ /**
61
+ * The tenant's resolved parent-chain config, materialised under the tenant's
62
+ * own id. Optional and opt-in on apply; see {@link ResolvedConfigBlock}.
63
+ */
64
+ resolved?: ResolvedConfigBlock;
59
65
  }
60
66
  /** Result of applying a payload — the projection result plus the key/tenant outcomes. */
61
67
  export interface ControlPlaneDefaultsApplyResult extends DefaultsProjectionResult {
62
68
  signingKeys: EntityProjectionOutcome;
63
69
  tenants: EntityProjectionOutcome;
70
+ /** Present when a `resolved` block was applied (or dry-run). */
71
+ resolved?: ApplyResolvedBlockResult;
64
72
  }
65
73
  /**
66
74
  * Reads the control plane's defaults + public signing keys off a control-plane
@@ -87,5 +95,12 @@ export declare function buildControlPlaneDefaultsPayload(controlPlaneAdapters: D
87
95
  export declare function applyControlPlaneDefaultsPayload(payload: ControlPlaneDefaultsPayload, targetAdapters: DataAdapters, controlPlaneTenantId: string, options?: {
88
96
  continueOnError?: boolean;
89
97
  entities?: DefaultsPayloadEntities;
98
+ /**
99
+ * Also apply the payload's `resolved` block to `tenantId`. Without this the
100
+ * block is ignored, so existing callers are unaffected.
101
+ */
102
+ resolved?: ApplyResolvedBlockOptions & {
103
+ tenantId: string;
104
+ };
90
105
  }): Promise<ControlPlaneDefaultsApplyResult>;
91
106
  //# sourceMappingURL=payload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/rollout/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,UAAU,EAKX,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EAQpB,MAAM,uBAAuB,CAAC;AAE/B;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,0BAA0B,GAAG;IACjE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,2BAA4B,SAAQ,mBAAmB;IACtE;;;;;OAKG;IACH,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B;;;;OAIG;IACH,OAAO,EAAE,sBAAsB,EAAE,CAAC;CACnC;AAED,yFAAyF;AACzF,MAAM,WAAW,+BAAgC,SAAQ,wBAAwB;IAC/E,WAAW,EAAE,uBAAuB,CAAC;IACrC,OAAO,EAAE,uBAAuB,CAAC;CAClC;AAkBD;;;;;;;;GAQG;AACH,wBAAsB,gCAAgC,CACpD,oBAAoB,EAAE,YAAY,EAClC,oBAAoB,EAAE,MAAM,EAC5B,QAAQ,GAAE,uBAA4B,EACtC,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,2BAA2B,CAAC,CAqCtC;AA0FD;;;;;;;;;;;GAWG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,2BAA2B,EACpC,cAAc,EAAE,YAAY,EAC5B,oBAAoB,EAAE,MAAM,EAC5B,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CAC/B,GACL,OAAO,CAAC,+BAA+B,CAAC,CAoD1C"}
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/rollout/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,UAAU,EAKX,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EAQpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EAEpB,MAAM,iBAAiB,CAAC;AAEzB;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,0BAA0B,GAAG;IACjE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,2BAA4B,SAAQ,mBAAmB;IACtE;;;;;OAKG;IACH,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B;;;;OAIG;IACH,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAChC;AAED,yFAAyF;AACzF,MAAM,WAAW,+BAAgC,SAAQ,wBAAwB;IAC/E,WAAW,EAAE,uBAAuB,CAAC;IACrC,OAAO,EAAE,uBAAuB,CAAC;IACjC,gEAAgE;IAChE,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAkBD;;;;;;;;GAQG;AACH,wBAAsB,gCAAgC,CACpD,oBAAoB,EAAE,YAAY,EAClC,oBAAoB,EAAE,MAAM,EAC5B,QAAQ,GAAE,uBAA4B,EACtC,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,2BAA2B,CAAC,CAqCtC;AA0FD;;;;;;;;;;;GAWG;AACH,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,2BAA2B,EACpC,cAAc,EAAE,YAAY,EAC5B,oBAAoB,EAAE,MAAM,EAC5B,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,EAAE,yBAAyB,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD,GACL,OAAO,CAAC,+BAA+B,CAAC,CA+D1C"}
@@ -0,0 +1,112 @@
1
+ import { Action, Branding, Connection, DataAdapters, EmailProvider, Hook, HookCode, KeyRing, PromptSetting, ResourceServer } from "authhero";
2
+ /**
3
+ * Sync of a tenant's resolved config (docs/design/tenant-config-inheritance.md,
4
+ * section 4.1). The block is the tenant's parent chain merged with
5
+ * `mergeConfig` and materialised under the **tenant's own id**. It carries only
6
+ * what is inherited, never the tenant's own rows.
7
+ *
8
+ * Rows get deterministic ids derived from the target tenant, the entity and
9
+ * the stable key, so a re-sync finds its rows by id and never touches a row the
10
+ * tenant owns. Secrets are copied as stored (ciphertext).
11
+ */
12
+ export type SyncEntity = "connection" | "resourceServer" | "hook" | "hookCode" | "action";
13
+ export declare const SYNC_ENTITIES: readonly ["connection", "resourceServer", "hookCode", "action", "hook"];
14
+ export interface ResolvedConfigBlock {
15
+ version: 1;
16
+ /** Ancestors the block was resolved from, nearest first. */
17
+ chain: string[];
18
+ connections: Connection[];
19
+ resourceServers: ResourceServer[];
20
+ hookCode: HookCode[];
21
+ actions: Action[];
22
+ hooks: Hook[];
23
+ emailProvider: EmailProvider | null;
24
+ branding: Branding | null;
25
+ promptSettings: PromptSetting | null;
26
+ /** `<entity>:<key>` of rows from `platform`-scoped ancestor rows. */
27
+ hidden: string[];
28
+ /** Explicit deletes. Only executed when the apply asks for `deletes`. */
29
+ deletes: Array<{
30
+ entity: SyncEntity;
31
+ key: string;
32
+ }>;
33
+ /** Content hash of everything above; equal hash means nothing to apply. */
34
+ hash: string;
35
+ }
36
+ export interface BuildResolvedBlockOptions {
37
+ /** Control plane used as implicit parent for tenants without `parent_tenant_id`. */
38
+ legacyControlPlane?: string;
39
+ maxDepth?: number;
40
+ deletes?: ResolvedConfigBlock["deletes"];
41
+ }
42
+ /**
43
+ * Deterministic id of a synced row: the type prefix, a `sy` marker and 15 hex
44
+ * characters of a hash of (tenant, entity, key). 17 characters after the
45
+ * prefix, the same shape as the ids each adapter generates.
46
+ */
47
+ export declare function syncedRowId(entity: SyncEntity, tenantId: string, key: string): Promise<string>;
48
+ /** The stable key a row is synced by (matches `mergeConfig`). */
49
+ export declare function keyOf(entity: SyncEntity, row: unknown): string;
50
+ /**
51
+ * Resolves `tenantId`'s parent chain into the block to push. Reads from
52
+ * `adapters`, which should be the layer that returns secrets as stored
53
+ * (ciphertext), so they are copied without being decrypted.
54
+ */
55
+ export declare function buildResolvedConfigBlock(adapters: DataAdapters, tenantId: string, options?: BuildResolvedBlockOptions): Promise<ResolvedConfigBlock>;
56
+ /**
57
+ * Checks that `ring` can decrypt every ciphertext in the block. Returns the
58
+ * key ids it cannot (never the values).
59
+ */
60
+ export declare function findUndecryptableKeyIds(block: ResolvedConfigBlock, ring: KeyRing): Promise<string[]>;
61
+ export interface ApplyResolvedBlockOptions {
62
+ /** Compute the diff and report it; write nothing. */
63
+ dryRun?: boolean;
64
+ /** Execute the block's explicit `deletes`. @default false */
65
+ deletes?: boolean;
66
+ /**
67
+ * Remove synced copies (`sy` ids) the block no longer carries, e.g. a row the
68
+ * parent stopped sharing. The tenant's own rows are never touched. A dry run
69
+ * lists them as `delete ...` whether or not this is set. @default false
70
+ */
71
+ prune?: boolean;
72
+ /** Apply even when the stored hash equals the block hash. */
73
+ force?: boolean;
74
+ /**
75
+ * The tenant's key ring. When given, the apply is refused before any write if
76
+ * it cannot decrypt a key id the block carries.
77
+ */
78
+ keyRing?: KeyRing;
79
+ /** Keep going after a failed row instead of throwing. @default true */
80
+ continueOnError?: boolean;
81
+ }
82
+ export interface SyncEntityOutcome {
83
+ added: number;
84
+ changed: number;
85
+ unchanged: number;
86
+ deleted: number;
87
+ errors: string[];
88
+ }
89
+ export interface ApplyResolvedBlockResult {
90
+ status: "applied" | "up-to-date" | "dry-run";
91
+ hash: string;
92
+ entities: Record<SyncEntity | "emailProvider" | "branding" | "promptSettings", SyncEntityOutcome>;
93
+ /** `<entity>:<key>` of rows that would be/were added, changed or deleted. */
94
+ changes: string[];
95
+ /**
96
+ * The same changes as structured rows, so a reader can tell an added row from
97
+ * a changed one, and a kept one from a removed one. Older senders omit it.
98
+ */
99
+ rows: SyncChangeRow[];
100
+ }
101
+ export interface SyncChangeRow {
102
+ entity: keyof ApplyResolvedBlockResult["entities"];
103
+ /** The row's key (`strategy:name`, identifier, name, `singleton`, ...). */
104
+ key: string;
105
+ /**
106
+ * `skipped`: the tenant has its own row with this key. `delete`: a copy that
107
+ * is or would be removed (removed only when the apply asked for it).
108
+ */
109
+ action: "added" | "changed" | "skipped" | "delete";
110
+ }
111
+ export declare function applyResolvedConfigBlock(block: ResolvedConfigBlock, target: DataAdapters, tenantId: string, options?: ApplyResolvedBlockOptions): Promise<ApplyResolvedBlockResult>;
112
+ //# sourceMappingURL=resolved-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolved-sync.d.ts","sourceRoot":"","sources":["../../../src/rollout/resolved-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { Rollout } from "authhero";
2
+ import type { RolloutDeps } from "./types";
3
+ export type RolloutTickOutcome = "skipped" | "waiting" | "planned-empty" | "paused" | "started" | "running" | "done";
4
+ export interface RolloutTickResult {
5
+ rolloutId: string;
6
+ outcome: RolloutTickOutcome;
7
+ /** Operations started by this tick. */
8
+ started: number;
9
+ /** The wave being worked on, when there is one. */
10
+ wave?: number;
11
+ }
12
+ /**
13
+ * Advances one rollout by one step. Stateless and idempotent: all state is the
14
+ * rollout row and its operations, so a tick can run from a cron, after a
15
+ * request, or twice at once.
16
+ *
17
+ * 1. A write-triggered rollout waits out its debounce, then is planned.
18
+ * 2. The current wave is the lowest one with unfinished operations. Before it
19
+ * starts, the previous wave is checked: the canary pauses the rollout on any
20
+ * failure, later waves when the failed fraction exceeds the threshold.
21
+ * 3. Up to `max_concurrent` pending operations of the current wave are started.
22
+ * 4. When every operation is finished the rollout is `done`.
23
+ */
24
+ export declare function advanceRollout(deps: RolloutDeps, rolloutOrId: Rollout | string): Promise<RolloutTickResult>;
25
+ export interface AdvanceRolloutsOptions {
26
+ /** Most rollouts to advance in one call. @default 20 */
27
+ limit?: number;
28
+ logger?: Pick<Console, "warn">;
29
+ }
30
+ /**
31
+ * Advances every open `config-sync` rollout one step. Meant for a host's
32
+ * scheduled handler (every few minutes). A rollout that throws does not stop
33
+ * the others.
34
+ */
35
+ export declare function advanceRollouts(deps: RolloutDeps, options?: AdvanceRolloutsOptions): Promise<RolloutTickResult[]>;
36
+ /** Pauses a rollout; nothing further is started until it is resumed. */
37
+ export declare function pauseRollout(deps: RolloutDeps, rolloutId: string, reason?: string): Promise<Rollout | null>;
38
+ /**
39
+ * Resumes a paused rollout, accepting the failures that paused it: the waves
40
+ * finished so far are no longer checked, and the next wave starts on the next
41
+ * tick. Tenants that failed are picked up again by the next drift reconcile.
42
+ */
43
+ export declare function resumeRollout(deps: RolloutDeps, rolloutId: string): Promise<Rollout | null>;
44
+ //# sourceMappingURL=advance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advance.d.ts","sourceRoot":"","sources":["../../../src/rollouts/advance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAmB,MAAM,UAAU,CAAC;AAUzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,SAAS,GACT,eAAe,GACf,QAAQ,GACR,SAAS,GACT,SAAS,GACT,MAAM,CAAC;AAEX,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAiCD;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,WAAW,EACjB,WAAW,EAAE,OAAO,GAAG,MAAM,GAC5B,OAAO,CAAC,iBAAiB,CAAC,CA6G5B;AAED,MAAM,WAAW,sBAAsB;IACrC,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAiB9B;AAED,wEAAwE;AACxE,wBAAsB,YAAY,CAChC,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,SAA0B,GAC/B,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAOzB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAoBzB"}
@@ -0,0 +1,54 @@
1
+ import type { Rollout } from "authhero";
2
+ /**
3
+ * Settings of a `config-sync` rollout, stored in the rollout's `config` column.
4
+ * Waves are cumulative percentages of the rolled-out tenants; the canary is a
5
+ * count that goes first. A wave is checked when it finishes: the canary pauses
6
+ * the rollout on any failure, later waves when the failed fraction exceeds
7
+ * `failure_threshold`.
8
+ */
9
+ export interface ConfigSyncRolloutConfig {
10
+ /** Tenants synced first, on their own. */
11
+ canary: number;
12
+ /** Cumulative percentages, ascending, ending at 100. */
13
+ waves: number[];
14
+ /** Failed fraction of a wave (0..1) above which the rollout pauses. */
15
+ failure_threshold: number;
16
+ /** Operations started per tick. */
17
+ max_concurrent: number;
18
+ /** Quiet time after the last write before a write-triggered rollout plans. */
19
+ debounce_ms: number;
20
+ /** What started it. */
21
+ trigger: "write" | "reconcile" | "manual";
22
+ /** The tenant whose descendants are rolled out to. */
23
+ root_tenant_id: string;
24
+ /** The tenant whose write requested it (write trigger). */
25
+ origin_tenant_id?: string;
26
+ /** Sync nothing, only report the diff. */
27
+ dry_run?: boolean;
28
+ /** Apply even when a tenant's stored hash matches. */
29
+ force?: boolean;
30
+ /** False while a write-triggered request waits out its debounce. */
31
+ planned?: boolean;
32
+ /** Tenants in the rollout, set when planned. */
33
+ tenant_count?: number;
34
+ /** Waves up to and including this one have been accepted by an operator. */
35
+ accepted_through?: number;
36
+ }
37
+ export declare const DEFAULT_ROLLOUT_WAVES: number[];
38
+ export declare const DEFAULT_ROLLOUT_SETTINGS: {
39
+ readonly canary: 1;
40
+ readonly waves: number[];
41
+ readonly failure_threshold: 0.1;
42
+ readonly max_concurrent: 25;
43
+ readonly debounce_ms: 60000;
44
+ };
45
+ /** Reads a rollout's config, filling defaults for anything missing. */
46
+ export declare function readRolloutConfig(rollout: Pick<Rollout, "config">): ConfigSyncRolloutConfig;
47
+ /**
48
+ * Assigns each of `count` tenants (already in rollout order) to a wave: wave 0
49
+ * is the canary, then one wave per percentage step. Boundaries are
50
+ * `ceil(count * pct / 100)`; empty waves are dropped and the last wave always
51
+ * reaches the end.
52
+ */
53
+ export declare function assignWaves(count: number, canary: number, waves: number[]): number[];
54
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/rollouts/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,uEAAuE;IACvE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IAEpB,uBAAuB;IACvB,OAAO,EAAE,OAAO,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC1C,sDAAsD;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,qBAAqB,UAAgB,CAAC;AAEnD,eAAO,MAAM,wBAAwB;;;;;;CAM3B,CAAC;AAEX,uEAAuE;AACvE,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,GAC/B,uBAAuB,CAYzB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EAAE,GACd,MAAM,EAAE,CA0BV"}
@@ -0,0 +1,29 @@
1
+ import type { Rollout } from "authhero";
2
+ import type { RolloutDeps } from "./types";
3
+ export interface CreateRolloutParams {
4
+ /** Roll out to the synced descendants of this tenant. Defaults to the control plane. */
5
+ rootTenantId?: string;
6
+ /** Limit the rollout to these tenants (those that are synced descendants). */
7
+ tenantIds?: string[];
8
+ canary?: number;
9
+ waves?: number[];
10
+ failureThreshold?: number;
11
+ /** Operations started per tick. */
12
+ maxConcurrent?: number;
13
+ dryRun?: boolean;
14
+ force?: boolean;
15
+ initiatedBy?: string;
16
+ }
17
+ export interface RolloutController {
18
+ /** Plans a manual rollout and starts its canary. */
19
+ create(params: CreateRolloutParams): Promise<Rollout>;
20
+ pause(id: string, reason?: string): Promise<Rollout | null>;
21
+ resume(id: string): Promise<Rollout | null>;
22
+ }
23
+ /**
24
+ * The operations a management API needs on rollouts that go beyond reading and
25
+ * updating rows. Wired by `initMultiTenant`, like the tenant operation
26
+ * executor.
27
+ */
28
+ export declare function createRolloutController(deps: RolloutDeps): RolloutController;
29
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/rollouts/controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAOxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,MAAM,WAAW,mBAAmB;IAClC,wFAAwF;IACxF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC5D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,WAAW,GAAG,iBAAiB,CAgC5E"}
@@ -0,0 +1,25 @@
1
+ import { type DataAdapters } from "authhero";
2
+ export interface FleetTenant {
3
+ tenantId: string;
4
+ /** Levels below the root; 1 for a direct child. */
5
+ depth: number;
6
+ /** The content hash last applied to the tenant, if any. */
7
+ appliedHash: string | null;
8
+ }
9
+ export interface EnumerateOptions {
10
+ /**
11
+ * The control plane a tenant without a `parent_tenant_id` inherits from, as
12
+ * `resolveTenantChain` uses it (`undefined` when the tenant opts out).
13
+ */
14
+ resolveLegacyParent: (tenantId: string) => Promise<string | undefined>;
15
+ /** Longest chain to follow before giving up on a tenant (cycle guard). */
16
+ maxDepth?: number;
17
+ }
18
+ /**
19
+ * The tenants below `rootId` that receive pushes (`config_sync: "synced"`),
20
+ * ordered by depth and then id, so a parent is always rolled out before its
21
+ * children. Parents are resolved like `resolveTenantChain`: `parent_tenant_id`,
22
+ * else the legacy control plane. Reads every tenant once.
23
+ */
24
+ export declare function listSyncedDescendants(adapters: Pick<DataAdapters, "tenants">, rootId: string, options: EnumerateOptions): Promise<FleetTenant[]>;
25
+ //# sourceMappingURL=enumerate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enumerate.d.ts","sourceRoot":"","sources":["../../../src/rollouts/enumerate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAe,MAAM,UAAU,CAAC;AAEpE,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACvE,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,EACvC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,WAAW,EAAE,CAAC,CA4CxB"}
@@ -0,0 +1,10 @@
1
+ import type { RolloutDeps } from "./types";
2
+ /** The tenant the sync would treat as the implicit parent of `tenantId`. */
3
+ export declare function resolveLegacyParent(deps: Pick<RolloutDeps, "controlPlaneTenantId" | "resolveControlPlane">, tenantId: string): Promise<string | undefined>;
4
+ /**
5
+ * The hash a sync of `tenantId` would store right now. The hash depends on the
6
+ * chain and its content, not on the tenant, so tenants that share a chain share
7
+ * one computation (memoised for the life of the returned function).
8
+ */
9
+ export declare function createExpectedHash(deps: Pick<RolloutDeps, "adapters" | "controlPlaneTenantId" | "resolveControlPlane" | "maxDepth">): (tenantId: string) => Promise<string>;
10
+ //# sourceMappingURL=hashes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hashes.d.ts","sourceRoot":"","sources":["../../../src/rollouts/hashes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,4EAA4E;AAC5E,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,sBAAsB,GAAG,qBAAqB,CAAC,EACvE,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAG7B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,CACR,WAAW,EACX,UAAU,GAAG,sBAAsB,GAAG,qBAAqB,GAAG,UAAU,CACzE,GACA,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAuBvC"}
@@ -0,0 +1,21 @@
1
+ export { DEFAULT_ROLLOUT_SETTINGS, DEFAULT_ROLLOUT_WAVES, assignWaves, readRolloutConfig, } from "./config";
2
+ export type { ConfigSyncRolloutConfig } from "./config";
3
+ export { listSyncedDescendants } from "./enumerate";
4
+ export type { EnumerateOptions, FleetTenant } from "./enumerate";
5
+ export { createExpectedHash } from "./hashes";
6
+ export { listRolloutOperations, planRollout } from "./plan";
7
+ export type { PlanResult } from "./plan";
8
+ export { advanceRollout, advanceRollouts, pauseRollout, resumeRollout, } from "./advance";
9
+ export type { AdvanceRolloutsOptions, RolloutTickOutcome, RolloutTickResult, } from "./advance";
10
+ export { verifyTenantConfig } from "./verify";
11
+ export type { ConfigSyncDifference, ConfigSyncVerification, VerifyConfigSyncDeps, } from "./verify";
12
+ export { getConfigSyncStatus } from "./status";
13
+ export type { ConfigSyncStatus, ConfigSyncStatusDeps } from "./status";
14
+ export { reconcileConfigDrift } from "./reconcile";
15
+ export type { ReconcileConfigDriftOptions, ReconcileConfigDriftResult, } from "./reconcile";
16
+ export { createRolloutWriteHooks, isPublishedRow, requestRollout, } from "./trigger";
17
+ export type { PublishableEntity, RolloutWriteHooks } from "./trigger";
18
+ export { createRolloutController } from "./controller";
19
+ export type { CreateRolloutParams, RolloutController } from "./controller";
20
+ export type { RolloutDeps } from "./types";
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/rollouts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,WAAW,EACX,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC5D,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EACL,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,YAAY,EACV,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EACV,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,cAAc,EACd,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC3E,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { Rollout, TenantOperation } from "authhero";
2
+ import type { RolloutDeps } from "./types";
3
+ export declare const OPEN_ROLLOUT_STATUSES: readonly ["pending", "canary", "rolling", "paused"];
4
+ export declare function storesOf(deps: RolloutDeps): {
5
+ tenantOperations: import("authhero").TenantOperationsAdapter;
6
+ tenantOperationEvents: import("authhero").TenantOperationEventsAdapter;
7
+ };
8
+ export declare function rolloutsOf(deps: RolloutDeps): import("authhero").RolloutsAdapter;
9
+ export interface PlanResult {
10
+ /** Tenants that get a sync operation. */
11
+ planned: number;
12
+ /** Candidates left out because they are already up to date. */
13
+ upToDate: number;
14
+ }
15
+ /**
16
+ * Turns a rollout into per-tenant `sync-defaults` operations: lists the synced
17
+ * descendants of the rollout's root (parents before children), leaves out the
18
+ * ones whose stored hash already matches (unless `force`), splits the rest into
19
+ * a canary and percentage waves, and creates one `pending` operation each. The
20
+ * rollout's `config` records the result. A rollout with nothing to do ends
21
+ * `done` (a write-triggered one, which exists only because something was
22
+ * written, is removed instead of leaving noise).
23
+ */
24
+ export declare function planRollout(deps: RolloutDeps, rollout: Rollout, options?: {
25
+ tenantIds?: string[];
26
+ }): Promise<PlanResult>;
27
+ /** Every operation of a rollout, oldest first. */
28
+ export declare function listRolloutOperations(deps: RolloutDeps, rolloutId: string): Promise<TenantOperation[]>;
29
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/rollouts/plan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAKzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,eAAO,MAAM,qBAAqB,qDAKxB,CAAC;AAEX,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW;;;EAMzC;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,sCAK3C;AAED,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GACrC,OAAO,CAAC,UAAU,CAAC,CAyErB;AAED,kDAAkD;AAClD,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,EAAE,CAAC,CAsB5B"}
@@ -0,0 +1,38 @@
1
+ import type { RolloutDeps } from "./types";
2
+ export interface ReconcileConfigDriftOptions {
3
+ /** The tenant whose descendants are checked. Defaults to the control plane. */
4
+ rootTenantId?: string;
5
+ /** Most tenants to report and roll out in one call. @default 500 */
6
+ limit?: number;
7
+ /**
8
+ * A tenant whose latest sync failed less than this long ago is reported but
9
+ * not rolled out again, so a tenant that keeps failing does not get a new
10
+ * rollout on every run. @default 3600000 (one hour)
11
+ */
12
+ retryAfterMs?: number;
13
+ logger?: Pick<Console, "warn">;
14
+ }
15
+ export interface ReconcileConfigDriftResult {
16
+ /** Synced tenants compared. */
17
+ checked: number;
18
+ /** Tenants whose applied hash differs from what their chain publishes. */
19
+ drifted: number;
20
+ /** Drifted tenants a running rollout already covers. */
21
+ alreadyCovered: number;
22
+ /** Drifted tenants left out because their latest sync failed recently. */
23
+ recentlyFailed: number;
24
+ /** The rollout created for the rest, if any. */
25
+ rolloutId?: string;
26
+ }
27
+ /**
28
+ * The safety net for lost triggers (design 4.3): compares every synced
29
+ * tenant's applied hash with the hash its chain would produce now. Drifted
30
+ * tenants get a `cfgdrift` log (queryable per tenant) and, unless an open
31
+ * rollout already covers them, one new rollout. Idempotent: running it again
32
+ * before the rollout finishes creates nothing, and once the tenants are synced
33
+ * there is nothing left to find.
34
+ *
35
+ * Run it from a scheduled handler, followed by `advanceRollouts`.
36
+ */
37
+ export declare function reconcileConfigDrift(deps: RolloutDeps, options?: ReconcileConfigDriftOptions): Promise<ReconcileConfigDriftResult>;
38
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../../src/rollouts/reconcile.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG3C,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,0BAA0B;IACzC,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,cAAc,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,cAAc,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,0BAA0B,CAAC,CA0IrC"}