@nebulr-group/bridge-auth-core 0.1.2 → 0.4.0-beta.1

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 (132) hide show
  1. package/dist/billing/bridge-subscription.d.ts +71 -0
  2. package/dist/billing/bridge-subscription.d.ts.map +1 -0
  3. package/dist/billing/bridge-subscription.js +209 -0
  4. package/dist/billing/bridge-subscription.js.map +1 -0
  5. package/dist/billing/entitlements-store.d.ts +61 -0
  6. package/dist/billing/entitlements-store.d.ts.map +1 -0
  7. package/dist/billing/entitlements-store.js +127 -0
  8. package/dist/billing/entitlements-store.js.map +1 -0
  9. package/dist/billing/fetch-billing-state.d.ts +9 -0
  10. package/dist/billing/fetch-billing-state.d.ts.map +1 -0
  11. package/dist/billing/fetch-billing-state.js +22 -0
  12. package/dist/billing/fetch-billing-state.js.map +1 -0
  13. package/dist/billing/lock-signal.d.ts +6 -0
  14. package/dist/billing/lock-signal.d.ts.map +1 -0
  15. package/dist/billing/lock-signal.js +8 -0
  16. package/dist/billing/lock-signal.js.map +1 -0
  17. package/dist/billing/quota-store.d.ts +86 -0
  18. package/dist/billing/quota-store.d.ts.map +1 -0
  19. package/dist/billing/quota-store.js +180 -0
  20. package/dist/billing/quota-store.js.map +1 -0
  21. package/dist/billing/types.d.ts +64 -0
  22. package/dist/billing/types.d.ts.map +1 -0
  23. package/dist/billing/types.js +49 -0
  24. package/dist/billing/types.js.map +1 -0
  25. package/dist/billing/use-bridge.d.ts +131 -0
  26. package/dist/billing/use-bridge.d.ts.map +1 -0
  27. package/dist/billing/use-bridge.js +181 -0
  28. package/dist/billing/use-bridge.js.map +1 -0
  29. package/dist/bridge-auth.d.ts +39 -1
  30. package/dist/bridge-auth.d.ts.map +1 -1
  31. package/dist/bridge-auth.js +89 -6
  32. package/dist/bridge-auth.js.map +1 -1
  33. package/dist/direct-auth.d.ts +1 -0
  34. package/dist/direct-auth.d.ts.map +1 -1
  35. package/dist/direct-auth.js +7 -0
  36. package/dist/direct-auth.js.map +1 -1
  37. package/dist/errors.d.ts +11 -0
  38. package/dist/errors.d.ts.map +1 -1
  39. package/dist/errors.js +14 -0
  40. package/dist/errors.js.map +1 -1
  41. package/dist/flags/attribute-providers.d.ts +229 -0
  42. package/dist/flags/attribute-providers.d.ts.map +1 -0
  43. package/dist/flags/attribute-providers.js +375 -0
  44. package/dist/flags/attribute-providers.js.map +1 -0
  45. package/dist/flags/dev-attribute-provider.d.ts +67 -0
  46. package/dist/flags/dev-attribute-provider.d.ts.map +1 -0
  47. package/dist/flags/dev-attribute-provider.js +200 -0
  48. package/dist/flags/dev-attribute-provider.js.map +1 -0
  49. package/dist/flags/evaluator.d.ts +58 -0
  50. package/dist/flags/evaluator.d.ts.map +1 -0
  51. package/dist/flags/evaluator.js +160 -0
  52. package/dist/flags/evaluator.js.map +1 -0
  53. package/dist/flags/flag.d.ts +199 -0
  54. package/dist/flags/flag.d.ts.map +1 -0
  55. package/dist/flags/flag.js +337 -0
  56. package/dist/flags/flag.js.map +1 -0
  57. package/dist/flags/identity.d.ts +77 -0
  58. package/dist/flags/identity.d.ts.map +1 -0
  59. package/dist/flags/identity.js +134 -0
  60. package/dist/flags/identity.js.map +1 -0
  61. package/dist/flags/index.d.ts +20 -0
  62. package/dist/flags/index.d.ts.map +1 -0
  63. package/dist/flags/index.js +21 -0
  64. package/dist/flags/index.js.map +1 -0
  65. package/dist/flags/operators.d.ts +63 -0
  66. package/dist/flags/operators.d.ts.map +1 -0
  67. package/dist/flags/operators.js +299 -0
  68. package/dist/flags/operators.js.map +1 -0
  69. package/dist/flags/propagation.d.ts +16 -0
  70. package/dist/flags/propagation.d.ts.map +1 -0
  71. package/dist/flags/propagation.js +107 -0
  72. package/dist/flags/propagation.js.map +1 -0
  73. package/dist/flags/realtime.d.ts +353 -0
  74. package/dist/flags/realtime.d.ts.map +1 -0
  75. package/dist/flags/realtime.js +779 -0
  76. package/dist/flags/realtime.js.map +1 -0
  77. package/dist/flags/runtime-mode.d.ts +32 -0
  78. package/dist/flags/runtime-mode.d.ts.map +1 -0
  79. package/dist/flags/runtime-mode.js +84 -0
  80. package/dist/flags/runtime-mode.js.map +1 -0
  81. package/dist/flags/telemetry.d.ts +79 -0
  82. package/dist/flags/telemetry.d.ts.map +1 -0
  83. package/dist/flags/telemetry.js +286 -0
  84. package/dist/flags/telemetry.js.map +1 -0
  85. package/dist/http.d.ts +4 -0
  86. package/dist/http.d.ts.map +1 -1
  87. package/dist/http.js +44 -12
  88. package/dist/http.js.map +1 -1
  89. package/dist/index.d.ts +14 -2
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +16 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/management-types.d.ts +38 -0
  94. package/dist/management-types.d.ts.map +1 -1
  95. package/dist/route-guard.d.ts.map +1 -1
  96. package/dist/route-guard.js +15 -5
  97. package/dist/route-guard.js.map +1 -1
  98. package/dist/token-manager.d.ts +3 -1
  99. package/dist/token-manager.d.ts.map +1 -1
  100. package/dist/token-manager.js +10 -6
  101. package/dist/token-manager.js.map +1 -1
  102. package/dist/types.d.ts +10 -2
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/usage/index.d.ts +3 -0
  105. package/dist/usage/index.d.ts.map +1 -0
  106. package/dist/usage/index.js +4 -0
  107. package/dist/usage/index.js.map +1 -0
  108. package/dist/usage/storage/durable-storage.d.ts +47 -0
  109. package/dist/usage/storage/durable-storage.d.ts.map +1 -0
  110. package/dist/usage/storage/durable-storage.js +27 -0
  111. package/dist/usage/storage/durable-storage.js.map +1 -0
  112. package/dist/usage/storage/index.d.ts +7 -0
  113. package/dist/usage/storage/index.d.ts.map +1 -0
  114. package/dist/usage/storage/index.js +28 -0
  115. package/dist/usage/storage/index.js.map +1 -0
  116. package/dist/usage/storage/indexeddb-storage.d.ts +18 -0
  117. package/dist/usage/storage/indexeddb-storage.d.ts.map +1 -0
  118. package/dist/usage/storage/indexeddb-storage.js +159 -0
  119. package/dist/usage/storage/indexeddb-storage.js.map +1 -0
  120. package/dist/usage/storage/node-fs-storage.d.ts +29 -0
  121. package/dist/usage/storage/node-fs-storage.d.ts.map +1 -0
  122. package/dist/usage/storage/node-fs-storage.js +180 -0
  123. package/dist/usage/storage/node-fs-storage.js.map +1 -0
  124. package/dist/usage/storage/noop-storage.d.ts +17 -0
  125. package/dist/usage/storage/noop-storage.d.ts.map +1 -0
  126. package/dist/usage/storage/noop-storage.js +67 -0
  127. package/dist/usage/storage/noop-storage.js.map +1 -0
  128. package/dist/usage/usage-reporter.d.ts +64 -0
  129. package/dist/usage/usage-reporter.d.ts.map +1 -0
  130. package/dist/usage/usage-reporter.js +234 -0
  131. package/dist/usage/usage-reporter.js.map +1 -0
  132. package/package.json +2 -1
@@ -0,0 +1,229 @@
1
+ import type { BridgeFlags } from './flag.js';
2
+ import type { BridgeSubscription } from '../billing/bridge-subscription.js';
3
+ import type { QuotaStore } from '../billing/quota-store.js';
4
+ import type { EntitlementsStore } from '../billing/entitlements-store.js';
5
+ /**
6
+ * A provider contributes a set of attributes for the current user/session.
7
+ * `provide()` is called on every flag eval; implementations should be cheap
8
+ * and synchronous (or fast async). Provider errors fall back to empty
9
+ * attributes — never break the eval.
10
+ */
11
+ export interface AttributeProvider {
12
+ /** Stable name for logging + collision messaging. */
13
+ readonly name: string;
14
+ /** Whether the keys this provider supplies count as bridge-managed (`bridge:`) or custom (`custom:`). */
15
+ readonly namespace?: 'bridge' | 'custom';
16
+ /**
17
+ * Return the attributes this provider currently supplies. May return a
18
+ * Promise; for hot paths, implementations should cache and return sync.
19
+ */
20
+ provide(): Record<string, unknown> | Promise<Record<string, unknown>>;
21
+ }
22
+ /**
23
+ * Registry attached to a BridgeFlags instance. Framework SDKs (bridge-svelte's
24
+ * Bridge.init) wire this up during bootstrap.
25
+ */
26
+ export declare class AttributeProviderRegistry {
27
+ private providers;
28
+ /** Register a provider. Idempotent on `name` — re-registering with the same name replaces. */
29
+ register(provider: AttributeProvider): void;
30
+ /** Remove a provider by name. */
31
+ unregister(name: string): void;
32
+ /** Number of providers currently registered. */
33
+ size(): number;
34
+ /** List provider names. */
35
+ names(): string[];
36
+ /**
37
+ * Collect attributes from every registered provider, merged in registration
38
+ * order. Later providers' keys overwrite earlier ones; this is INTERNAL
39
+ * merge order — dev-supplied attributes always win at the call boundary
40
+ * (handled in `applyTo`).
41
+ *
42
+ * Provider failures are isolated — one provider throwing doesn't block the
43
+ * rest. The failing provider contributes an empty attribute set for that call.
44
+ */
45
+ collect(): Promise<Record<string, unknown>>;
46
+ /**
47
+ * Sync variant of `collect()` — used by `BridgeFlags.flag()` on the hot eval
48
+ * path (FF 2.0 evaluates inline on every flag check, so the merge must be
49
+ * sync). Async providers are SKIPPED for this eval; they should self-cache
50
+ * their result and return sync values once warmed.
51
+ *
52
+ * Same isolation guarantee as `collect()`: one throwing provider doesn't
53
+ * block the rest.
54
+ */
55
+ collectSync(): Record<string, unknown>;
56
+ /**
57
+ * Apply provider attributes to a BridgeFlags instance's global context.
58
+ * Should be called on a sensible cadence by the framework SDK — typically:
59
+ * - once at bootstrap
60
+ * - when auth state changes (logout/login, role change)
61
+ * - on a periodic refresh if attributes drift
62
+ *
63
+ * Dev-supplied attributes are preserved on collision (locked decision #20).
64
+ */
65
+ applyTo(bridge: BridgeFlags): Promise<void>;
66
+ }
67
+ /**
68
+ * Shape of the JWT claims that AuthAttributeProvider reads. Every field is
69
+ * optional — the provider emits an attribute only when the corresponding
70
+ * claim is present.
71
+ */
72
+ export interface AuthJwtClaims {
73
+ /** Subject — the user's id. */
74
+ sub?: string;
75
+ role?: string;
76
+ email?: string;
77
+ /** Tenant id. */
78
+ tid?: string;
79
+ /** Tenant plan (mirrored into `tenant.plan`). Authoritative source for
80
+ * `bridge:billing.plan` is the BillingAttributeProvider — keep them in sync. */
81
+ plan?: string;
82
+ /** Privilege list (or a single comma-joined string). */
83
+ privileges?: string[] | string;
84
+ /** Catch-all so unknown claims don't break the type. */
85
+ [k: string]: unknown;
86
+ }
87
+ /**
88
+ * Configuration for `AuthAttributeProvider`. The framework SDK supplies a
89
+ * sync getter that returns the current decoded JWT claims (or `undefined`
90
+ * when logged out). Sync read is critical: FF 2.0 evaluates inline.
91
+ */
92
+ export interface AuthProviderConfig {
93
+ getClaims: () => AuthJwtClaims | undefined;
94
+ }
95
+ /**
96
+ * Canonical auth-derived attribute source. Reads decoded JWT claims through
97
+ * a sync callback the framework SDK provides, and flattens them into the
98
+ * eval namespace:
99
+ * - `user.id` ← `sub`
100
+ * - `user.role` ← `role`
101
+ * - `user.email` ← `email`
102
+ * - `tenant.id` ← `tid`
103
+ * - `tenant.plan` ← `plan`
104
+ * - `privileges` ← `privileges` (array or string)
105
+ *
106
+ * Construct with no config for the empty stub (every workspace gets the
107
+ * provider in its registry by default; unconfigured ones contribute nothing).
108
+ */
109
+ export declare class AuthAttributeProvider implements AttributeProvider {
110
+ readonly name = "bridge:auth";
111
+ readonly namespace: "bridge";
112
+ private readonly config;
113
+ constructor(config?: AuthProviderConfig);
114
+ provide(): Record<string, unknown>;
115
+ }
116
+ /**
117
+ * A snapshot of the current billing state. All fields optional — apps can
118
+ * surface only what they have. `quota` exposes `{used, limit}` per resource;
119
+ * the provider auto-derives `percent_used` when both fields are numeric and
120
+ * `limit > 0`. `limit` exposes scalar plan caps (seats, max_projects, etc).
121
+ */
122
+ export interface BillingSnapshot {
123
+ /** Current plan tier (e.g. 'FREE' | 'TEAM' | 'PRO'). */
124
+ plan?: string;
125
+ /** True when the tenant is on a time-limited trial. */
126
+ trial?: boolean;
127
+ /** Metered usage per resource. */
128
+ quota?: Record<string, {
129
+ used?: number;
130
+ limit?: number;
131
+ }>;
132
+ /** Plan-defined scalar caps. */
133
+ limit?: Record<string, number | string>;
134
+ }
135
+ /**
136
+ * Configuration for `BillingAttributeProvider`. The dev supplies a callable
137
+ * that returns the current snapshot — sync or async. Returning `undefined`
138
+ * means "no billing data right now" → the provider contributes no attributes.
139
+ */
140
+ export interface BillingProviderConfig {
141
+ getBillingSnapshot: () => BillingSnapshot | Promise<BillingSnapshot | undefined> | undefined;
142
+ }
143
+ /**
144
+ * Billing 2.0 US-13 — store-backed wiring for the BillingAttributeProvider.
145
+ *
146
+ * Framework wrappers pass the three Phase A/B stores from `useBridge()`. The
147
+ * provider reads them synchronously on every flag eval and flattens the live
148
+ * state into the `bridge:billing.*` namespace:
149
+ * - subscription: `plan`, `trial`, `subscription.status`
150
+ * - quotas: `quota.<metric>.{used,limit,remaining,percent_used}`
151
+ * - entitlements: `entitlement.<name>` (incl. `entitlement.app_active`)
152
+ *
153
+ * All store reads are O(stores in cache). `provide()` MUST stay sync — the FF
154
+ * 2.0 eval path calls it inline on every flag check. No HTTP, no awaits.
155
+ */
156
+ export interface BillingProviderStores {
157
+ /** `useBridge().subscription` — reactive container for canonical sub state. */
158
+ subscription?: BridgeSubscription;
159
+ /** `useBridge().quotas` — per-metric snapshot cache. */
160
+ quotas?: QuotaStore;
161
+ /** `useBridge().entitlementsStore` — fail-closed boolean map. */
162
+ entitlements?: EntitlementsStore;
163
+ }
164
+ export declare class BillingAttributeProvider implements AttributeProvider {
165
+ readonly name = "bridge:billing";
166
+ readonly namespace: "bridge";
167
+ private readonly config;
168
+ private stores;
169
+ private warnedOnce;
170
+ /**
171
+ * Construct with an explicit config that supplies the billing snapshot.
172
+ * No config → treated as an empty provider (returns `{}` on every call)
173
+ * so accidentally instantiating without wiring doesn't crash.
174
+ */
175
+ constructor(config?: BillingProviderConfig);
176
+ /**
177
+ * Billing 2.0 US-13 — wire the three reactive stores from `useBridge()` so
178
+ * `provide()` can flatten live billing state synchronously on every flag
179
+ * eval. Idempotent: re-binding replaces the previous store references. Any
180
+ * subset of stores may be supplied — missing stores simply contribute no
181
+ * keys to the flattened map (eg. unattached subscription → no `plan` key).
182
+ *
183
+ * Framework wrappers (bridge-svelte's `Bridge.init`) call this once after
184
+ * `useBridge()` has been bootstrapped, then `register()` the provider on
185
+ * the FF 2.0 AttributeProviderRegistry.
186
+ */
187
+ bindStores(stores: BillingProviderStores): void;
188
+ /**
189
+ * Flatten the live billing state into the `bridge:billing.*` namespace.
190
+ *
191
+ * Two sources are merged:
192
+ * 1. US-13 store path: reads the three `useBridge()` stores synchronously
193
+ * and emits canonical `plan`, `trial`, `subscription.status`,
194
+ * `quota.<metric>.*`, and `entitlement.<name>` keys.
195
+ * 2. Legacy `getBillingSnapshot` callback path (pre-US-13): preserved so
196
+ * standalone-FF apps that wired the provider before US-13 keep
197
+ * working. Store-derived keys win on collision (newer = canonical).
198
+ *
199
+ * The store path is sync, no HTTP, no awaits — safe in the FF 2.0 hot eval
200
+ * path. The legacy path may be async; when it is, the merged result is a
201
+ * Promise (consumers awaiting `provide()` already handle this).
202
+ *
203
+ * Failures in any branch degrade silently to whatever was successfully
204
+ * collected — never throws, never breaks the eval.
205
+ */
206
+ provide(): Record<string, unknown> | Promise<Record<string, unknown>>;
207
+ /**
208
+ * US-13 — read the three stores and emit the canonical `bridge:billing.*`
209
+ * flat map. Sync, defensive: every store ref is optional and every read is
210
+ * wrapped so a single misbehaving store can't break the eval path.
211
+ *
212
+ * Output key set per `BillingAttributeProvider`'s ticket contract:
213
+ * - `bridge:billing.plan` string (plan slug)
214
+ * - `bridge:billing.trial` boolean
215
+ * - `bridge:billing.subscription.status` string
216
+ * - `bridge:billing.quota.<metric>.used` number
217
+ * - `bridge:billing.quota.<metric>.limit` number
218
+ * - `bridge:billing.quota.<metric>.remaining` number
219
+ * - `bridge:billing.quota.<metric>.percent_used` number (0..1+)
220
+ * - `bridge:billing.entitlement.<name>` boolean (incl. `app_active`)
221
+ *
222
+ * Note: `bridge:billing.limit.<name>` (non-quota plan caps like seats) is
223
+ * reserved for a future story — no live source today, so it's left empty.
224
+ */
225
+ private flattenStores;
226
+ private flatten;
227
+ private warnOnce;
228
+ }
229
+ //# sourceMappingURL=attribute-providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute-providers.d.ts","sourceRoot":"","sources":["../../src/flags/attribute-providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,375 @@
1
+ // AttributeProvider plugin model for Bridge Feature Flags (TBP-173).
2
+ //
3
+ // AttributeProvider is THE canonical mechanism for feeding attributes into
4
+ // flag evaluation. Every framework SDK wires the bridge-managed providers
5
+ // (`AuthAttributeProvider`, `BillingAttributeProvider`) automatically on
6
+ // bootstrap so `user.role`, `tenant.plan`, billing entitlements etc. flow in
7
+ // without app code. Apps push their own state into eval by implementing
8
+ // `AttributeProvider` and `register()`ing the instance on the registry — that
9
+ // is the canonical pattern for any attribute backed by app state (cohort,
10
+ // route segment, current workspace, anything reactive).
11
+ //
12
+ // Per-call attributes (via `setContext` or the `<FeatureFlag context>` /
13
+ // `useFlag(key, default, context)` prop) are the *override* path — for
14
+ // transient, one-off, or per-instance values, and to override a provider
15
+ // value at a specific call site. Collision rule (locked decision #20):
16
+ // dev-supplied attributes WIN over provider-supplied attributes on key
17
+ // overlap. The admin UI surfaces the collision so it's debuggable (TBP-178).
18
+ /**
19
+ * Registry attached to a BridgeFlags instance. Framework SDKs (bridge-svelte's
20
+ * Bridge.init) wire this up during bootstrap.
21
+ */
22
+ export class AttributeProviderRegistry {
23
+ providers = [];
24
+ /** Register a provider. Idempotent on `name` — re-registering with the same name replaces. */
25
+ register(provider) {
26
+ if (!provider.name) {
27
+ throw new Error('AttributeProvider must have a non-empty name');
28
+ }
29
+ this.providers = this.providers.filter((p) => p.name !== provider.name);
30
+ this.providers.push(provider);
31
+ }
32
+ /** Remove a provider by name. */
33
+ unregister(name) {
34
+ this.providers = this.providers.filter((p) => p.name !== name);
35
+ }
36
+ /** Number of providers currently registered. */
37
+ size() {
38
+ return this.providers.length;
39
+ }
40
+ /** List provider names. */
41
+ names() {
42
+ return this.providers.map((p) => p.name);
43
+ }
44
+ /**
45
+ * Collect attributes from every registered provider, merged in registration
46
+ * order. Later providers' keys overwrite earlier ones; this is INTERNAL
47
+ * merge order — dev-supplied attributes always win at the call boundary
48
+ * (handled in `applyTo`).
49
+ *
50
+ * Provider failures are isolated — one provider throwing doesn't block the
51
+ * rest. The failing provider contributes an empty attribute set for that call.
52
+ */
53
+ async collect() {
54
+ const out = {};
55
+ for (const provider of this.providers) {
56
+ try {
57
+ const attrs = await provider.provide();
58
+ Object.assign(out, attrs ?? {});
59
+ }
60
+ catch {
61
+ // Silently skip a failing provider for this eval.
62
+ }
63
+ }
64
+ return out;
65
+ }
66
+ /**
67
+ * Sync variant of `collect()` — used by `BridgeFlags.flag()` on the hot eval
68
+ * path (FF 2.0 evaluates inline on every flag check, so the merge must be
69
+ * sync). Async providers are SKIPPED for this eval; they should self-cache
70
+ * their result and return sync values once warmed.
71
+ *
72
+ * Same isolation guarantee as `collect()`: one throwing provider doesn't
73
+ * block the rest.
74
+ */
75
+ collectSync() {
76
+ const out = {};
77
+ for (const provider of this.providers) {
78
+ try {
79
+ const attrs = provider.provide();
80
+ if (attrs instanceof Promise) {
81
+ // Async providers can't participate in the sync hot path. They run
82
+ // through `collect()`/`applyTo()` on demand instead.
83
+ continue;
84
+ }
85
+ Object.assign(out, attrs ?? {});
86
+ }
87
+ catch {
88
+ // Silently skip a failing provider for this eval.
89
+ }
90
+ }
91
+ return out;
92
+ }
93
+ /**
94
+ * Apply provider attributes to a BridgeFlags instance's global context.
95
+ * Should be called on a sensible cadence by the framework SDK — typically:
96
+ * - once at bootstrap
97
+ * - when auth state changes (logout/login, role change)
98
+ * - on a periodic refresh if attributes drift
99
+ *
100
+ * Dev-supplied attributes are preserved on collision (locked decision #20).
101
+ */
102
+ async applyTo(bridge) {
103
+ const providerAttrs = await this.collect();
104
+ const current = bridge.getContext().attributes;
105
+ // Provider attrs first, dev-supplied attrs second (dev wins on collision)
106
+ bridge.setContext({
107
+ identity: bridge.getContext().identity,
108
+ attributes: { ...providerAttrs, ...current },
109
+ }, false);
110
+ }
111
+ }
112
+ /**
113
+ * Canonical auth-derived attribute source. Reads decoded JWT claims through
114
+ * a sync callback the framework SDK provides, and flattens them into the
115
+ * eval namespace:
116
+ * - `user.id` ← `sub`
117
+ * - `user.role` ← `role`
118
+ * - `user.email` ← `email`
119
+ * - `tenant.id` ← `tid`
120
+ * - `tenant.plan` ← `plan`
121
+ * - `privileges` ← `privileges` (array or string)
122
+ *
123
+ * Construct with no config for the empty stub (every workspace gets the
124
+ * provider in its registry by default; unconfigured ones contribute nothing).
125
+ */
126
+ export class AuthAttributeProvider {
127
+ name = 'bridge:auth';
128
+ namespace = 'bridge';
129
+ config;
130
+ constructor(config) {
131
+ this.config = config ?? { getClaims: () => undefined };
132
+ }
133
+ provide() {
134
+ let claims;
135
+ try {
136
+ claims = this.config.getClaims();
137
+ }
138
+ catch {
139
+ return {};
140
+ }
141
+ if (!claims || typeof claims !== 'object')
142
+ return {};
143
+ const out = {};
144
+ if (typeof claims.sub === 'string' && claims.sub.length > 0) {
145
+ out['user.id'] = claims.sub;
146
+ }
147
+ if (typeof claims.role === 'string') {
148
+ out['user.role'] = claims.role;
149
+ }
150
+ if (typeof claims.email === 'string') {
151
+ out['user.email'] = claims.email;
152
+ }
153
+ if (typeof claims.tid === 'string') {
154
+ out['tenant.id'] = claims.tid;
155
+ }
156
+ if (typeof claims.plan === 'string') {
157
+ out['tenant.plan'] = claims.plan;
158
+ }
159
+ if (Array.isArray(claims.privileges)) {
160
+ out['privileges'] = claims.privileges;
161
+ }
162
+ else if (typeof claims.privileges === 'string') {
163
+ out['privileges'] = claims.privileges;
164
+ }
165
+ return out;
166
+ }
167
+ }
168
+ const BILLING_NS_PREFIX = 'bridge:billing.';
169
+ export class BillingAttributeProvider {
170
+ name = 'bridge:billing';
171
+ namespace = 'bridge';
172
+ config;
173
+ stores = {};
174
+ warnedOnce = false;
175
+ /**
176
+ * Construct with an explicit config that supplies the billing snapshot.
177
+ * No config → treated as an empty provider (returns `{}` on every call)
178
+ * so accidentally instantiating without wiring doesn't crash.
179
+ */
180
+ constructor(config) {
181
+ this.config = config ?? { getBillingSnapshot: () => undefined };
182
+ }
183
+ /**
184
+ * Billing 2.0 US-13 — wire the three reactive stores from `useBridge()` so
185
+ * `provide()` can flatten live billing state synchronously on every flag
186
+ * eval. Idempotent: re-binding replaces the previous store references. Any
187
+ * subset of stores may be supplied — missing stores simply contribute no
188
+ * keys to the flattened map (eg. unattached subscription → no `plan` key).
189
+ *
190
+ * Framework wrappers (bridge-svelte's `Bridge.init`) call this once after
191
+ * `useBridge()` has been bootstrapped, then `register()` the provider on
192
+ * the FF 2.0 AttributeProviderRegistry.
193
+ */
194
+ bindStores(stores) {
195
+ this.stores = { ...stores };
196
+ }
197
+ /**
198
+ * Flatten the live billing state into the `bridge:billing.*` namespace.
199
+ *
200
+ * Two sources are merged:
201
+ * 1. US-13 store path: reads the three `useBridge()` stores synchronously
202
+ * and emits canonical `plan`, `trial`, `subscription.status`,
203
+ * `quota.<metric>.*`, and `entitlement.<name>` keys.
204
+ * 2. Legacy `getBillingSnapshot` callback path (pre-US-13): preserved so
205
+ * standalone-FF apps that wired the provider before US-13 keep
206
+ * working. Store-derived keys win on collision (newer = canonical).
207
+ *
208
+ * The store path is sync, no HTTP, no awaits — safe in the FF 2.0 hot eval
209
+ * path. The legacy path may be async; when it is, the merged result is a
210
+ * Promise (consumers awaiting `provide()` already handle this).
211
+ *
212
+ * Failures in any branch degrade silently to whatever was successfully
213
+ * collected — never throws, never breaks the eval.
214
+ */
215
+ provide() {
216
+ // US-13 — store-backed path. Synchronous, no HTTP. Reads the live state
217
+ // of the three Phase A/B stores (subscription, quotas, entitlements) and
218
+ // flattens into the `bridge:billing.*` namespace. Safe to call before any
219
+ // store is wired — missing stores simply contribute no keys.
220
+ const storeAttrs = this.flattenStores();
221
+ // Legacy path — the `getBillingSnapshot` callback config. Preserved so
222
+ // standalone-FF apps that wired the provider before US-13 keep working.
223
+ let result;
224
+ try {
225
+ result = this.config.getBillingSnapshot();
226
+ }
227
+ catch (err) {
228
+ this.warnOnce(err);
229
+ return storeAttrs;
230
+ }
231
+ if (result instanceof Promise) {
232
+ // Async legacy snapshot — merge async; store attrs are returned now and
233
+ // also re-emitted under the resolved promise. Provider attrs from the
234
+ // store path win on collision (newer = US-13 canonical).
235
+ return result.then((snap) => ({ ...this.flatten(snap), ...storeAttrs }), (err) => {
236
+ this.warnOnce(err);
237
+ return storeAttrs;
238
+ });
239
+ }
240
+ // Sync legacy snapshot (or undefined) — merge sync. Store attrs win.
241
+ const legacyAttrs = this.flatten(result);
242
+ return { ...legacyAttrs, ...storeAttrs };
243
+ }
244
+ /**
245
+ * US-13 — read the three stores and emit the canonical `bridge:billing.*`
246
+ * flat map. Sync, defensive: every store ref is optional and every read is
247
+ * wrapped so a single misbehaving store can't break the eval path.
248
+ *
249
+ * Output key set per `BillingAttributeProvider`'s ticket contract:
250
+ * - `bridge:billing.plan` string (plan slug)
251
+ * - `bridge:billing.trial` boolean
252
+ * - `bridge:billing.subscription.status` string
253
+ * - `bridge:billing.quota.<metric>.used` number
254
+ * - `bridge:billing.quota.<metric>.limit` number
255
+ * - `bridge:billing.quota.<metric>.remaining` number
256
+ * - `bridge:billing.quota.<metric>.percent_used` number (0..1+)
257
+ * - `bridge:billing.entitlement.<name>` boolean (incl. `app_active`)
258
+ *
259
+ * Note: `bridge:billing.limit.<name>` (non-quota plan caps like seats) is
260
+ * reserved for a future story — no live source today, so it's left empty.
261
+ */
262
+ flattenStores() {
263
+ const out = {};
264
+ // Subscription — plan slug, trial flag, status string.
265
+ try {
266
+ const sub = this.stores.subscription;
267
+ if (sub) {
268
+ const snap = sub.snapshot();
269
+ const state = snap.state;
270
+ if (state) {
271
+ if (state.plan && typeof state.plan.slug === 'string') {
272
+ out[`${BILLING_NS_PREFIX}plan`] = state.plan.slug;
273
+ }
274
+ if (typeof state.status === 'string') {
275
+ out[`${BILLING_NS_PREFIX}subscription.status`] = state.status;
276
+ out[`${BILLING_NS_PREFIX}trial`] = state.status === 'trial';
277
+ }
278
+ }
279
+ }
280
+ }
281
+ catch (err) {
282
+ this.warnOnce(err);
283
+ }
284
+ // Quotas — per-metric used / limit / remaining / percent_used.
285
+ try {
286
+ const quotas = this.stores.quotas;
287
+ if (quotas) {
288
+ const all = quotas.getAll();
289
+ for (const [metric, snap] of all.entries()) {
290
+ if (!snap)
291
+ continue;
292
+ const base = `${BILLING_NS_PREFIX}quota.${metric}`;
293
+ if (typeof snap.used === 'number')
294
+ out[`${base}.used`] = snap.used;
295
+ if (typeof snap.limit === 'number')
296
+ out[`${base}.limit`] = snap.limit;
297
+ if (typeof snap.remaining === 'number') {
298
+ out[`${base}.remaining`] = snap.remaining;
299
+ }
300
+ if (typeof snap.percent_used === 'number') {
301
+ out[`${base}.percent_used`] = snap.percent_used;
302
+ }
303
+ }
304
+ }
305
+ }
306
+ catch (err) {
307
+ this.warnOnce(err);
308
+ }
309
+ // Entitlements — boolean per name (incl. `app_active`).
310
+ try {
311
+ const ent = this.stores.entitlements;
312
+ if (ent && ent.isHydrated()) {
313
+ const all = ent.all();
314
+ for (const [name, value] of Object.entries(all)) {
315
+ if (typeof value === 'boolean') {
316
+ out[`${BILLING_NS_PREFIX}entitlement.${name}`] = value;
317
+ }
318
+ }
319
+ }
320
+ }
321
+ catch (err) {
322
+ this.warnOnce(err);
323
+ }
324
+ return out;
325
+ }
326
+ flatten(snapshot) {
327
+ if (!snapshot || typeof snapshot !== 'object')
328
+ return {};
329
+ const out = {};
330
+ if (typeof snapshot.plan === 'string') {
331
+ out[`${BILLING_NS_PREFIX}plan`] = snapshot.plan;
332
+ }
333
+ if (typeof snapshot.trial === 'boolean') {
334
+ out[`${BILLING_NS_PREFIX}trial`] = snapshot.trial;
335
+ }
336
+ if (snapshot.quota && typeof snapshot.quota === 'object') {
337
+ for (const [resource, q] of Object.entries(snapshot.quota)) {
338
+ if (!q || typeof q !== 'object')
339
+ continue;
340
+ const base = `${BILLING_NS_PREFIX}quota.${resource}`;
341
+ const used = typeof q.used === 'number' ? q.used : undefined;
342
+ const limit = typeof q.limit === 'number' ? q.limit : undefined;
343
+ if (used !== undefined)
344
+ out[`${base}.used`] = used;
345
+ if (limit !== undefined)
346
+ out[`${base}.limit`] = limit;
347
+ if (used !== undefined && limit !== undefined && limit > 0) {
348
+ out[`${base}.percent_used`] = Math.floor((used / limit) * 100);
349
+ }
350
+ }
351
+ }
352
+ if (snapshot.limit && typeof snapshot.limit === 'object') {
353
+ for (const [name, value] of Object.entries(snapshot.limit)) {
354
+ if (typeof value === 'number' || typeof value === 'string') {
355
+ out[`${BILLING_NS_PREFIX}limit.${name}`] = value;
356
+ }
357
+ }
358
+ }
359
+ return out;
360
+ }
361
+ warnOnce(err) {
362
+ if (this.warnedOnce)
363
+ return;
364
+ this.warnedOnce = true;
365
+ try {
366
+ // eslint-disable-next-line no-console
367
+ globalThis.console?.warn?.(`[BillingAttributeProvider] getBillingSnapshot threw; ` +
368
+ `returning empty attributes. Error: ${err?.message ?? String(err)}`);
369
+ }
370
+ catch {
371
+ // ignore console errors
372
+ }
373
+ }
374
+ }
375
+ //# sourceMappingURL=attribute-providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute-providers.js","sourceRoot":"","sources":["../../src/flags/attribute-providers.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,2EAA2E;AAC3E,0EAA0E;AAC1E,yEAAyE;AACzE,6EAA6E;AAC7E,wEAAwE;AACxE,8EAA8E;AAC9E,0EAA0E;AAC1E,wDAAwD;AACxD,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,yEAAyE;AACzE,uEAAuE;AACvE,uEAAuE;AACvE,6EAA6E;AAyB7E;;;GAGG;AACH,MAAM,OAAO,yBAAyB;IAC5B,SAAS,GAAwB,EAAE,CAAC;IAE5C,8FAA8F;IAC9F,QAAQ,CAAC,QAA2B;QAClC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,CAAC;QACxE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,iCAAiC;IACjC,UAAU,CAAC,IAAY;QACrB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACjE,CAAC;IAED,gDAAgD;IAChD,IAAI;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,2BAA2B;IAC3B,KAAK;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACvC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,kDAAkD;YACpD,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;;;;OAQG;IACH,WAAW;QACT,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACjC,IAAI,KAAK,YAAY,OAAO,EAAE,CAAC;oBAC7B,mEAAmE;oBACnE,qDAAqD;oBACrD,SAAS;gBACX,CAAC;gBACD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,kDAAkD;YACpD,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,CAAC,MAAmB;QAC/B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,UAAU,CAAC;QAC/C,0EAA0E;QAC1E,MAAM,CAAC,UAAU,CACf;YACE,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,QAAQ;YACtC,UAAU,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,EAAE;SAC7C,EACD,KAAK,CACN,CAAC;IACJ,CAAC;CACF;AA0CD;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,qBAAqB;IACvB,IAAI,GAAG,aAAa,CAAC;IACrB,SAAS,GAAG,QAAiB,CAAC;IAEtB,MAAM,CAAqB;IAE5C,YAAY,MAA2B;QACrC,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;IACzD,CAAC;IAED,OAAO;QACL,IAAI,MAAiC,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QAErD,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5D,GAAG,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;QAC9B,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,GAAG,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;QACjC,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrC,GAAG,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;QACnC,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACnC,GAAG,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;QAChC,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,GAAG,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;QACnC,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;QACxC,CAAC;aAAM,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACjD,GAAG,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;QACxC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAmFD,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAE5C,MAAM,OAAO,wBAAwB;IAC1B,IAAI,GAAG,gBAAgB,CAAC;IACxB,SAAS,GAAG,QAAiB,CAAC;IAEtB,MAAM,CAAwB;IACvC,MAAM,GAA0B,EAAE,CAAC;IACnC,UAAU,GAAG,KAAK,CAAC;IAE3B;;;;OAIG;IACH,YAAY,MAA8B;QACxC,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC;IAClE,CAAC;IAED;;;;;;;;;;OAUG;IACH,UAAU,CAAC,MAA6B;QACtC,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO;QAGL,wEAAwE;QACxE,yEAAyE;QACzE,0EAA0E;QAC1E,6DAA6D;QAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAExC,uEAAuE;QACvE,wEAAwE;QACxE,IAAI,MAA+D,CAAC;QACpE,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC5C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACnB,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC9B,wEAAwE;YACxE,sEAAsE;YACtE,yDAAyD;YACzD,OAAO,MAAM,CAAC,IAAI,CAChB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC,EACpD,CAAC,GAAG,EAAE,EAAE;gBACN,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBACnB,OAAO,UAAU,CAAC;YACpB,CAAC,CACF,CAAC;QACJ,CAAC;QACD,qEAAqE;QACrE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,EAAE,GAAG,WAAW,EAAE,GAAG,UAAU,EAAE,CAAC;IAC3C,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACK,aAAa;QACnB,MAAM,GAAG,GAA4B,EAAE,CAAC;QAExC,uDAAuD;QACvD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;YACrC,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;gBACzB,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,KAAK,CAAC,IAAI,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;wBACtD,GAAG,CAAC,GAAG,iBAAiB,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;oBACpD,CAAC;oBACD,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;wBACrC,GAAG,CAAC,GAAG,iBAAiB,qBAAqB,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;wBAC9D,GAAG,CAAC,GAAG,iBAAiB,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC;oBAC9D,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QAED,+DAA+D;QAC/D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YAClC,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC5B,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;oBAC3C,IAAI,CAAC,IAAI;wBAAE,SAAS;oBACpB,MAAM,IAAI,GAAG,GAAG,iBAAiB,SAAS,MAAM,EAAE,CAAC;oBACnD,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;wBAAE,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;oBACnE,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;wBAAE,GAAG,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;oBACtE,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;wBACvC,GAAG,CAAC,GAAG,IAAI,YAAY,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;oBAC5C,CAAC;oBACD,IAAI,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;wBAC1C,GAAG,CAAC,GAAG,IAAI,eAAe,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC;oBAClD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QAED,wDAAwD;QACxD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;YACrC,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;gBACtB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChD,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;wBAC/B,GAAG,CAAC,GAAG,iBAAiB,eAAe,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC;oBACzD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,OAAO,CAAC,QAAqC;QACnD,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QAEzD,MAAM,GAAG,GAA4B,EAAE,CAAC;QAExC,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,GAAG,iBAAiB,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;QAClD,CAAC;QACD,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACxC,GAAG,CAAC,GAAG,iBAAiB,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;QACpD,CAAC;QAED,IAAI,QAAQ,CAAC,KAAK,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACzD,KAAK,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3D,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;oBAAE,SAAS;gBAC1C,MAAM,IAAI,GAAG,GAAG,iBAAiB,SAAS,QAAQ,EAAE,CAAC;gBACrD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;gBAChE,IAAI,IAAI,KAAK,SAAS;oBAAE,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,IAAI,CAAC;gBACnD,IAAI,KAAK,KAAK,SAAS;oBAAE,GAAG,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,KAAK,CAAC;gBACtD,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBAC3D,GAAG,CAAC,GAAG,IAAI,eAAe,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;gBACjE,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,KAAK,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACzD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC3D,GAAG,CAAC,GAAG,iBAAiB,SAAS,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,QAAQ,CAAC,GAAY;QAC3B,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC;YACH,sCAAsC;YACrC,UAAkB,CAAC,OAAO,EAAE,IAAI,EAAE,CACjC,uDAAuD;gBACrD,sCAAuC,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CACjF,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;CACF"}