@pipeline-builder/api-core 0.0.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.
- package/LICENSE +202 -0
- package/README.md +98 -0
- package/lib/constants/ai-providers.d.ts +52 -0
- package/lib/constants/ai-providers.js +129 -0
- package/lib/constants/http-status.d.ts +20 -0
- package/lib/constants/http-status.js +26 -0
- package/lib/constants/index.d.ts +3 -0
- package/lib/constants/index.js +6 -0
- package/lib/constants/time.d.ts +10 -0
- package/lib/constants/time.js +13 -0
- package/lib/errors/app-errors.d.ts +30 -0
- package/lib/errors/app-errors.js +53 -0
- package/lib/errors/index.d.ts +1 -0
- package/lib/errors/index.js +4 -0
- package/lib/helpers/access-helpers.d.ts +63 -0
- package/lib/helpers/access-helpers.js +82 -0
- package/lib/helpers/crud-helpers.d.ts +9 -0
- package/lib/helpers/crud-helpers.js +23 -0
- package/lib/helpers/index.d.ts +6 -0
- package/lib/helpers/index.js +9 -0
- package/lib/helpers/org-hierarchy-http.d.ts +74 -0
- package/lib/helpers/org-hierarchy-http.js +144 -0
- package/lib/helpers/org-hierarchy.d.ts +57 -0
- package/lib/helpers/org-hierarchy.js +110 -0
- package/lib/helpers/restore-helpers.d.ts +49 -0
- package/lib/helpers/restore-helpers.js +78 -0
- package/lib/helpers/sse-helpers.d.ts +20 -0
- package/lib/helpers/sse-helpers.js +45 -0
- package/lib/index.d.ts +58 -0
- package/lib/index.js +71 -0
- package/lib/middleware/auth.d.ts +208 -0
- package/lib/middleware/auth.js +588 -0
- package/lib/middleware/index.d.ts +3 -0
- package/lib/middleware/index.js +6 -0
- package/lib/middleware/mongo-sanitize.d.ts +32 -0
- package/lib/middleware/mongo-sanitize.js +100 -0
- package/lib/middleware/step-up.d.ts +45 -0
- package/lib/middleware/step-up.js +138 -0
- package/lib/openapi/extend-zod.d.ts +1 -0
- package/lib/openapi/extend-zod.js +6 -0
- package/lib/openapi/index.d.ts +2 -0
- package/lib/openapi/index.js +5 -0
- package/lib/openapi/registry.d.ts +17 -0
- package/lib/openapi/registry.js +38 -0
- package/lib/openapi/routes/ask-routes.d.ts +7 -0
- package/lib/openapi/routes/ask-routes.js +62 -0
- package/lib/openapi/routes/billing-routes.d.ts +1 -0
- package/lib/openapi/routes/billing-routes.js +66 -0
- package/lib/openapi/routes/image-registry-routes.d.ts +7 -0
- package/lib/openapi/routes/image-registry-routes.js +98 -0
- package/lib/openapi/routes/index.d.ts +5 -0
- package/lib/openapi/routes/index.js +28 -0
- package/lib/openapi/routes/message-routes.d.ts +1 -0
- package/lib/openapi/routes/message-routes.js +105 -0
- package/lib/openapi/routes/pipeline-routes.d.ts +1 -0
- package/lib/openapi/routes/pipeline-routes.js +105 -0
- package/lib/openapi/routes/pipeline-template-routes.d.ts +1 -0
- package/lib/openapi/routes/pipeline-template-routes.js +61 -0
- package/lib/openapi/routes/plugin-routes.d.ts +1 -0
- package/lib/openapi/routes/plugin-routes.js +96 -0
- package/lib/openapi/routes/quota-routes.d.ts +1 -0
- package/lib/openapi/routes/quota-routes.js +62 -0
- package/lib/openapi/schema-registry.d.ts +25 -0
- package/lib/openapi/schema-registry.js +91 -0
- package/lib/routes/health.d.ts +41 -0
- package/lib/routes/health.js +82 -0
- package/lib/routes/index.d.ts +1 -0
- package/lib/routes/index.js +4 -0
- package/lib/services/audit-spool.d.ts +80 -0
- package/lib/services/audit-spool.js +172 -0
- package/lib/services/cache-service.d.ts +124 -0
- package/lib/services/cache-service.js +276 -0
- package/lib/services/circuit-breaker.d.ts +45 -0
- package/lib/services/circuit-breaker.js +138 -0
- package/lib/services/compliance-client.d.ts +46 -0
- package/lib/services/compliance-client.js +128 -0
- package/lib/services/compliance-event-subscriber.d.ts +16 -0
- package/lib/services/compliance-event-subscriber.js +72 -0
- package/lib/services/durable-event-bus.d.ts +96 -0
- package/lib/services/durable-event-bus.js +204 -0
- package/lib/services/entity-events.d.ts +48 -0
- package/lib/services/entity-events.js +79 -0
- package/lib/services/env-redis.d.ts +44 -0
- package/lib/services/env-redis.js +94 -0
- package/lib/services/http-client.d.ts +143 -0
- package/lib/services/http-client.js +335 -0
- package/lib/services/index.d.ts +18 -0
- package/lib/services/index.js +20 -0
- package/lib/services/leader-lock.d.ts +45 -0
- package/lib/services/leader-lock.js +85 -0
- package/lib/services/quota.d.ts +130 -0
- package/lib/services/quota.js +264 -0
- package/lib/services/remote-audit-client.d.ts +160 -0
- package/lib/services/remote-audit-client.js +390 -0
- package/lib/services/retry-strategy.d.ts +74 -0
- package/lib/services/retry-strategy.js +118 -0
- package/lib/services/scheduler.d.ts +41 -0
- package/lib/services/scheduler.js +86 -0
- package/lib/services/service-boot.d.ts +20 -0
- package/lib/services/service-boot.js +28 -0
- package/lib/services/sse-ticket-store.d.ts +51 -0
- package/lib/services/sse-ticket-store.js +130 -0
- package/lib/services/token-revocation.d.ts +52 -0
- package/lib/services/token-revocation.js +120 -0
- package/lib/testing/tier-mock.d.ts +44 -0
- package/lib/testing/tier-mock.js +65 -0
- package/lib/types/audit-events.d.ts +69 -0
- package/lib/types/audit-events.js +4 -0
- package/lib/types/catalog-metadata.d.ts +36 -0
- package/lib/types/catalog-metadata.js +21 -0
- package/lib/types/common.d.ts +255 -0
- package/lib/types/common.js +41 -0
- package/lib/types/error-codes.d.ts +54 -0
- package/lib/types/error-codes.js +107 -0
- package/lib/types/feature-flags.d.ts +36 -0
- package/lib/types/feature-flags.js +128 -0
- package/lib/types/http.d.ts +27 -0
- package/lib/types/http.js +4 -0
- package/lib/types/index.d.ts +11 -0
- package/lib/types/index.js +14 -0
- package/lib/types/permissions.d.ts +65 -0
- package/lib/types/permissions.js +131 -0
- package/lib/types/pipeline-template.d.ts +30 -0
- package/lib/types/pipeline-template.js +13 -0
- package/lib/types/pipeline.d.ts +59 -0
- package/lib/types/pipeline.js +31 -0
- package/lib/types/quota-tiers.d.ts +79 -0
- package/lib/types/quota-tiers.js +221 -0
- package/lib/types/visibility.d.ts +20 -0
- package/lib/types/visibility.js +22 -0
- package/lib/utils/alias-resolver.d.ts +37 -0
- package/lib/utils/alias-resolver.js +68 -0
- package/lib/utils/audit.d.ts +15 -0
- package/lib/utils/audit.js +39 -0
- package/lib/utils/aws-scrub.d.ts +11 -0
- package/lib/utils/aws-scrub.js +67 -0
- package/lib/utils/compliance-attributes.d.ts +6 -0
- package/lib/utils/compliance-attributes.js +69 -0
- package/lib/utils/concurrency.d.ts +9 -0
- package/lib/utils/concurrency.js +29 -0
- package/lib/utils/crash-handlers.d.ts +18 -0
- package/lib/utils/crash-handlers.js +36 -0
- package/lib/utils/env.d.ts +28 -0
- package/lib/utils/env.js +54 -0
- package/lib/utils/headers.d.ts +18 -0
- package/lib/utils/headers.js +21 -0
- package/lib/utils/identity.d.ts +40 -0
- package/lib/utils/identity.js +51 -0
- package/lib/utils/index.d.ts +17 -0
- package/lib/utils/index.js +20 -0
- package/lib/utils/logger.d.ts +38 -0
- package/lib/utils/logger.js +174 -0
- package/lib/utils/metric-emitter.d.ts +36 -0
- package/lib/utils/metric-emitter.js +32 -0
- package/lib/utils/object.d.ts +13 -0
- package/lib/utils/object.js +18 -0
- package/lib/utils/params.d.ts +150 -0
- package/lib/utils/params.js +206 -0
- package/lib/utils/response.d.ts +117 -0
- package/lib/utils/response.js +223 -0
- package/lib/utils/safe-require.d.ts +13 -0
- package/lib/utils/safe-require.js +19 -0
- package/lib/utils/secret-encryption.d.ts +176 -0
- package/lib/utils/secret-encryption.js +374 -0
- package/lib/utils/ssrf.d.ts +30 -0
- package/lib/utils/ssrf.js +106 -0
- package/lib/validation/ai-schemas.d.ts +56 -0
- package/lib/validation/ai-schemas.js +78 -0
- package/lib/validation/common-schemas.d.ts +133 -0
- package/lib/validation/common-schemas.js +94 -0
- package/lib/validation/index.d.ts +7 -0
- package/lib/validation/index.js +10 -0
- package/lib/validation/message-schemas.d.ts +160 -0
- package/lib/validation/message-schemas.js +156 -0
- package/lib/validation/middleware.d.ts +72 -0
- package/lib/validation/middleware.js +65 -0
- package/lib/validation/pipeline-schemas.d.ts +181 -0
- package/lib/validation/pipeline-schemas.js +101 -0
- package/lib/validation/pipeline-template-schemas.d.ts +155 -0
- package/lib/validation/pipeline-template-schemas.js +66 -0
- package/lib/validation/plugin-schemas.d.ts +171 -0
- package/lib/validation/plugin-schemas.js +81 -0
- package/openapi.yaml +292 -0
- package/package.json +167 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Available quota tier identifiers.
|
|
2
|
+
*
|
|
3
|
+
* `unlimited` is a special tier: every quota is `-1` (uncapped) and it includes
|
|
4
|
+
* every feature/add-on bundle. It is the DEFAULT when billing is disabled (no
|
|
5
|
+
* metering/enforcement surface exists, so nothing is capped), and it is NEVER
|
|
6
|
+
* shown or selectable when billing is enabled — see `STANDARD_TIERS`. */
|
|
7
|
+
export type QuotaTier = 'developer' | 'pro' | 'team' | 'enterprise' | 'unlimited';
|
|
8
|
+
/** Limit values for each quota type within a tier. */
|
|
9
|
+
export interface QuotaTierLimits {
|
|
10
|
+
plugins: number;
|
|
11
|
+
pipelines: number;
|
|
12
|
+
apiCalls: number;
|
|
13
|
+
aiCalls: number;
|
|
14
|
+
/**
|
|
15
|
+
* Aggregate registry storage cap in BYTES. Counted across every repo
|
|
16
|
+
* under the org's `org-{orgId}/` namespace. -1 means unlimited.
|
|
17
|
+
* push-gate reads this; the image-registry rejects token issuance for
|
|
18
|
+
* `push` scope when the org's measured usage exceeds the limit.
|
|
19
|
+
*/
|
|
20
|
+
storageBytes: number;
|
|
21
|
+
/** Count-quotas on the user-editable feature tables added to close per-org
|
|
22
|
+
* DoS via spam. -1 means unlimited. */
|
|
23
|
+
dashboards: number;
|
|
24
|
+
alertRules: number;
|
|
25
|
+
alertDestinations: number;
|
|
26
|
+
idpConfigs: number;
|
|
27
|
+
/**
|
|
28
|
+
* Max org members (active users / seats). -1 = unlimited. This is the "Team"
|
|
29
|
+
* tier differentiator — enforced at member-invite time (an invite is blocked
|
|
30
|
+
* when active members + pending invites would exceed this).
|
|
31
|
+
*/
|
|
32
|
+
seats: number;
|
|
33
|
+
/**
|
|
34
|
+
* Reporting retention in DAYS — NOT a flow quota (never decremented, absent
|
|
35
|
+
* from `VALID_QUOTA_TYPES`): these ride the tier-baseline + bundle-grant math
|
|
36
|
+
* purely as an entitlement the billing service syncs to reporting's
|
|
37
|
+
* `dora_settings`. -1 = unlimited (the sweep skips the org entirely).
|
|
38
|
+
* `eventRetentionDays` — non-deploy `pipeline_events` (STAGE/ACTION/build).
|
|
39
|
+
* `doraRetentionDays` — deploy events + `deployment_outcomes` + `incidents`,
|
|
40
|
+
* and the per-org report-query window for DORA routes.
|
|
41
|
+
* Extendable via the `retention_pack` / `dora_history_pack` add-on bundles.
|
|
42
|
+
*/
|
|
43
|
+
eventRetentionDays: number;
|
|
44
|
+
doraRetentionDays: number;
|
|
45
|
+
}
|
|
46
|
+
/** Full preset for a single tier (label + limits). */
|
|
47
|
+
export interface QuotaTierPreset {
|
|
48
|
+
label: string;
|
|
49
|
+
limits: QuotaTierLimits;
|
|
50
|
+
}
|
|
51
|
+
export declare const QUOTA_TIERS: Record<QuotaTier, QuotaTierPreset>;
|
|
52
|
+
/** All valid tier names (incl. `unlimited`). Used for validation of a *stored*
|
|
53
|
+
* tier — `unlimited` is a valid value even though it's never offered for sale. */
|
|
54
|
+
export declare const VALID_TIERS: readonly QuotaTier[];
|
|
55
|
+
/** The standard, billing-selectable tiers — the ones offered as purchasable plans
|
|
56
|
+
* and shown in tier pickers. Derived as "every valid tier except `unlimited`",
|
|
57
|
+
* which is the billing-DISABLED default and is never displayed/selectable when
|
|
58
|
+
* billing is enabled. Kept DRY off `VALID_TIERS` so adding a tier flows through. */
|
|
59
|
+
export declare const STANDARD_TIERS: readonly QuotaTier[];
|
|
60
|
+
/** Tiers that permit the org → team hierarchy (nesting teams under a root). The
|
|
61
|
+
* billing-off `unlimited` tier is team-capable (it's the most permissive); the
|
|
62
|
+
* entry-level `developer`/`pro` tiers are not. Single source for the parent-
|
|
63
|
+
* eligibility + downgrade-overcap checks so they can't drift. */
|
|
64
|
+
export declare const TEAM_CAPABLE_TIERS: readonly QuotaTier[];
|
|
65
|
+
export declare function tierAllowsTeams(tier: string | undefined | null): boolean;
|
|
66
|
+
/** Whether the billing service is enabled in this deployment (`BILLING_ENABLED`,
|
|
67
|
+
* opt-out default-on — mirrors the billing/platform configs). With billing OFF
|
|
68
|
+
* there's no metering/enforcement surface, so the default tier is `unlimited`. */
|
|
69
|
+
export declare function isBillingEnabled(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Default tier assigned to new organizations.
|
|
72
|
+
* - Billing DISABLED → `unlimited` (nothing is metered, so everything is uncapped).
|
|
73
|
+
* - Billing ENABLED → `DEFAULT_QUOTA_TIER` if it's a valid standard tier, else `developer`.
|
|
74
|
+
*/
|
|
75
|
+
export declare const DEFAULT_TIER: QuotaTier;
|
|
76
|
+
/** Check whether a string is a valid QuotaTier. */
|
|
77
|
+
export declare function isValidTier(value: string): value is QuotaTier;
|
|
78
|
+
/** Get the default limits for a given tier (falls back to developer). */
|
|
79
|
+
export declare function getTierLimits(tier: string): QuotaTierLimits;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Preset limits for each tier. -1 means unlimited.
|
|
5
|
+
*
|
|
6
|
+
* AI calls are sized much smaller than `apiCalls` because each call has
|
|
7
|
+
* external provider cost (~$0.01$0.10/call). Developer tier allows light
|
|
8
|
+
* exploration (50/period); Pro lifts to 2,500; Enterprise is capped high
|
|
9
|
+
* (25,000) — fair-use, not literally unlimited.
|
|
10
|
+
*
|
|
11
|
+
* `storageBytes` is the aggregate registry cap per org. Sized
|
|
12
|
+
* around plugin-image realities: a typical plugin image is 200500 MB;
|
|
13
|
+
* Developer's 2 GB holds ~4 versions × ~500 MB, Pro's 50 GB covers a
|
|
14
|
+
* mature catalog. Operators can override per-org via the quota CRUD API.
|
|
15
|
+
*/
|
|
16
|
+
const GB = 1024 * 1024 * 1024;
|
|
17
|
+
/**
|
|
18
|
+
* Code-default limits per tier — the fallback when no env override is set.
|
|
19
|
+
* -1 means unlimited. (Counts sized to "comfortably enough for one team, not
|
|
20
|
+
* script spam": 20 dashboards, 50 alert rules, 10 destinations, 1 IdP config
|
|
21
|
+
* for Developer; scaled up for Pro; -1 (uncapped) for the cheap count-quotas
|
|
22
|
+
* on Team/Enterprise while cost-driving quotas — incl. apiCalls — stay finite.)
|
|
23
|
+
*/
|
|
24
|
+
const DEFAULT_TIER_LIMITS = {
|
|
25
|
+
// Free tier: single seat, 2 pipelines, apiCalls CAPPED (was unlimited — a
|
|
26
|
+
// DoS/abuse hole on a shared resource); aiCalls small (each has ~$0.01-0.10
|
|
27
|
+
// external cost). Lean base — growth happens by upgrading, not stacking here.
|
|
28
|
+
developer: {
|
|
29
|
+
plugins: 25,
|
|
30
|
+
pipelines: 2,
|
|
31
|
+
apiCalls: 25_000,
|
|
32
|
+
aiCalls: 25,
|
|
33
|
+
storageBytes: 2 * GB,
|
|
34
|
+
dashboards: 20,
|
|
35
|
+
alertRules: 50,
|
|
36
|
+
alertDestinations: 10,
|
|
37
|
+
idpConfigs: 1,
|
|
38
|
+
seats: 1,
|
|
39
|
+
eventRetentionDays: 30,
|
|
40
|
+
doraRetentionDays: 180,
|
|
41
|
+
},
|
|
42
|
+
// Pro = individual power user, single seat, individual pricing. A 2nd seat (or
|
|
43
|
+
// team collaboration) requires the Team tier — the `seat` add-on is Team+ only,
|
|
44
|
+
// keeping Team the collaboration tier. Pro's value over Developer is its richer
|
|
45
|
+
// call/storage/plugin ceilings + feature add-ons (SSO/audit/DORA), not seats.
|
|
46
|
+
pro: {
|
|
47
|
+
plugins: 50,
|
|
48
|
+
pipelines: 5,
|
|
49
|
+
apiCalls: 250_000,
|
|
50
|
+
aiCalls: 1_000,
|
|
51
|
+
storageBytes: 25 * GB,
|
|
52
|
+
dashboards: 200,
|
|
53
|
+
alertRules: 500,
|
|
54
|
+
alertDestinations: 50,
|
|
55
|
+
idpConfigs: 5,
|
|
56
|
+
seats: 1,
|
|
57
|
+
eventRetentionDays: 30,
|
|
58
|
+
doraRetentionDays: 180,
|
|
59
|
+
},
|
|
60
|
+
// Team = collaboration tier; the seat limit (3) is the real differentiator over
|
|
61
|
+
// Pro (single-seat) — it's the multi-seat collaboration floor. Lean base ($79):
|
|
62
|
+
// growth rides the seat/pipeline/etc add-ons (land-and-expand). Limits sit
|
|
63
|
+
// between Pro and Enterprise.
|
|
64
|
+
team: {
|
|
65
|
+
plugins: 75,
|
|
66
|
+
pipelines: 6,
|
|
67
|
+
apiCalls: 500_000,
|
|
68
|
+
aiCalls: 2_500,
|
|
69
|
+
storageBytes: 60 * GB,
|
|
70
|
+
dashboards: -1,
|
|
71
|
+
alertRules: -1,
|
|
72
|
+
alertDestinations: -1,
|
|
73
|
+
idpConfigs: 5,
|
|
74
|
+
seats: 3,
|
|
75
|
+
eventRetentionDays: 30,
|
|
76
|
+
doraRetentionDays: 180,
|
|
77
|
+
},
|
|
78
|
+
// Enterprise ($599, held): the all-inclusive tier — 15 seats, 30 pipelines, ALL
|
|
79
|
+
// premium features included (see TIER_FEATURES). FAIR-USE — cost drivers (apiCalls,
|
|
80
|
+
// aiCalls, storageBytes) capped so one account can't run up unbounded
|
|
81
|
+
// compute/provider/storage cost on a flat price; cheap count-quotas stay -1.
|
|
82
|
+
enterprise: {
|
|
83
|
+
plugins: 150,
|
|
84
|
+
pipelines: 30,
|
|
85
|
+
apiCalls: 900_000,
|
|
86
|
+
aiCalls: 9_000,
|
|
87
|
+
storageBytes: 250 * GB,
|
|
88
|
+
dashboards: -1,
|
|
89
|
+
alertRules: -1,
|
|
90
|
+
alertDestinations: -1,
|
|
91
|
+
idpConfigs: -1,
|
|
92
|
+
seats: 15,
|
|
93
|
+
eventRetentionDays: 30,
|
|
94
|
+
doraRetentionDays: 180,
|
|
95
|
+
},
|
|
96
|
+
// Unlimited: EVERY quota uncapped (-1). The default when billing is disabled
|
|
97
|
+
// (no enforcement surface) — never shown/selectable when billing is enabled.
|
|
98
|
+
unlimited: {
|
|
99
|
+
plugins: -1,
|
|
100
|
+
pipelines: -1,
|
|
101
|
+
apiCalls: -1,
|
|
102
|
+
aiCalls: -1,
|
|
103
|
+
storageBytes: -1,
|
|
104
|
+
dashboards: -1,
|
|
105
|
+
alertRules: -1,
|
|
106
|
+
alertDestinations: -1,
|
|
107
|
+
idpConfigs: -1,
|
|
108
|
+
seats: -1,
|
|
109
|
+
eventRetentionDays: -1,
|
|
110
|
+
doraRetentionDays: -1,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Read an integer env var, falling back to the code default. `-1` = unlimited.
|
|
115
|
+
* Rejects (→ fallback) anything that isn't a clean integer string and any value
|
|
116
|
+
* `< -1`: a decimal (`50.5`) or a nonsense negative (`-5`) would otherwise ship a
|
|
117
|
+
* broken finite limit (parity with `envCents`'s rigor for prices).
|
|
118
|
+
*/
|
|
119
|
+
function envInt(name, fallback) {
|
|
120
|
+
const raw = process.env[name];
|
|
121
|
+
if (raw === undefined || raw === '')
|
|
122
|
+
return fallback;
|
|
123
|
+
const trimmed = raw.trim();
|
|
124
|
+
if (!/^-?\d+$/.test(trimmed))
|
|
125
|
+
return fallback; // no decimals / non-numeric
|
|
126
|
+
const n = parseInt(trimmed, 10);
|
|
127
|
+
return Number.isNaN(n) || n < -1 ? fallback : n;
|
|
128
|
+
}
|
|
129
|
+
/** Read a string env var, falling back to the code default. */
|
|
130
|
+
function envStr(name, fallback) {
|
|
131
|
+
const raw = process.env[name];
|
|
132
|
+
return raw === undefined || raw === '' ? fallback : raw;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Per-tier limits, each overridable via `QUOTA_TIER_<TIER>_<LIMIT>` env vars
|
|
136
|
+
* (e.g. `QUOTA_TIER_PRO_PIPELINES=250`, `QUOTA_TIER_DEVELOPER_STORAGE_BYTES=...`).
|
|
137
|
+
* Unset/empty → the code default. `-1` = unlimited. Read once at module load —
|
|
138
|
+
* on k8s these flow in via the `app-env` ConfigMap (built from `.env`).
|
|
139
|
+
*/
|
|
140
|
+
function tierLimits(tier) {
|
|
141
|
+
// `unlimited` is uncapped BY DEFINITION: EVERY quota is -1 and it is NOT
|
|
142
|
+
// env-overridable. Reading QUOTA_TIER_UNLIMITED_* here would let a stray env
|
|
143
|
+
// var silently cap the billing-DISABLED default tier — surfacing as a spurious
|
|
144
|
+
// "quota exceeded" on a deploy that meters nothing. Derive -1 for every field
|
|
145
|
+
// from the limits shape so a newly-added quota is uncapped here automatically.
|
|
146
|
+
if (tier === 'unlimited') {
|
|
147
|
+
const uncapped = { ...DEFAULT_TIER_LIMITS.unlimited };
|
|
148
|
+
for (const k of Object.keys(uncapped))
|
|
149
|
+
uncapped[k] = -1;
|
|
150
|
+
return uncapped;
|
|
151
|
+
}
|
|
152
|
+
const d = DEFAULT_TIER_LIMITS[tier];
|
|
153
|
+
const T = tier.toUpperCase();
|
|
154
|
+
return {
|
|
155
|
+
plugins: envInt(`QUOTA_TIER_${T}_PLUGINS`, d.plugins),
|
|
156
|
+
pipelines: envInt(`QUOTA_TIER_${T}_PIPELINES`, d.pipelines),
|
|
157
|
+
apiCalls: envInt(`QUOTA_TIER_${T}_API_CALLS`, d.apiCalls),
|
|
158
|
+
aiCalls: envInt(`QUOTA_TIER_${T}_AI_CALLS`, d.aiCalls),
|
|
159
|
+
storageBytes: envInt(`QUOTA_TIER_${T}_STORAGE_BYTES`, d.storageBytes),
|
|
160
|
+
dashboards: envInt(`QUOTA_TIER_${T}_DASHBOARDS`, d.dashboards),
|
|
161
|
+
alertRules: envInt(`QUOTA_TIER_${T}_ALERT_RULES`, d.alertRules),
|
|
162
|
+
alertDestinations: envInt(`QUOTA_TIER_${T}_ALERT_DESTINATIONS`, d.alertDestinations),
|
|
163
|
+
idpConfigs: envInt(`QUOTA_TIER_${T}_IDP_CONFIGS`, d.idpConfigs),
|
|
164
|
+
seats: envInt(`QUOTA_TIER_${T}_SEATS`, d.seats),
|
|
165
|
+
eventRetentionDays: envInt(`QUOTA_TIER_${T}_EVENT_RETENTION_DAYS`, d.eventRetentionDays),
|
|
166
|
+
doraRetentionDays: envInt(`QUOTA_TIER_${T}_DORA_RETENTION_DAYS`, d.doraRetentionDays),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// Labels are overridable via `QUOTA_TIER_<TIER>_LABEL` (display name only).
|
|
170
|
+
export const QUOTA_TIERS = {
|
|
171
|
+
developer: { label: envStr('QUOTA_TIER_DEVELOPER_LABEL', 'Developer'), limits: tierLimits('developer') },
|
|
172
|
+
pro: { label: envStr('QUOTA_TIER_PRO_LABEL', 'Pro'), limits: tierLimits('pro') },
|
|
173
|
+
team: { label: envStr('QUOTA_TIER_TEAM_LABEL', 'Team'), limits: tierLimits('team') },
|
|
174
|
+
enterprise: { label: envStr('QUOTA_TIER_ENTERPRISE_LABEL', 'Enterprise'), limits: tierLimits('enterprise') },
|
|
175
|
+
unlimited: { label: envStr('QUOTA_TIER_UNLIMITED_LABEL', 'Unlimited'), limits: tierLimits('unlimited') },
|
|
176
|
+
};
|
|
177
|
+
/** All valid tier names (incl. `unlimited`). Used for validation of a *stored*
|
|
178
|
+
* tier — `unlimited` is a valid value even though it's never offered for sale. */
|
|
179
|
+
export const VALID_TIERS = Object.keys(QUOTA_TIERS);
|
|
180
|
+
/** The standard, billing-selectable tiers — the ones offered as purchasable plans
|
|
181
|
+
* and shown in tier pickers. Derived as "every valid tier except `unlimited`",
|
|
182
|
+
* which is the billing-DISABLED default and is never displayed/selectable when
|
|
183
|
+
* billing is enabled. Kept DRY off `VALID_TIERS` so adding a tier flows through. */
|
|
184
|
+
export const STANDARD_TIERS = VALID_TIERS.filter((t) => t !== 'unlimited');
|
|
185
|
+
/** Tiers that permit the org → team hierarchy (nesting teams under a root). The
|
|
186
|
+
* billing-off `unlimited` tier is team-capable (it's the most permissive); the
|
|
187
|
+
* entry-level `developer`/`pro` tiers are not. Single source for the parent-
|
|
188
|
+
* eligibility + downgrade-overcap checks so they can't drift. */
|
|
189
|
+
export const TEAM_CAPABLE_TIERS = ['team', 'enterprise', 'unlimited'];
|
|
190
|
+
export function tierAllowsTeams(tier) {
|
|
191
|
+
return !!tier && TEAM_CAPABLE_TIERS.includes(tier);
|
|
192
|
+
}
|
|
193
|
+
/** Whether the billing service is enabled in this deployment (`BILLING_ENABLED`,
|
|
194
|
+
* opt-out default-on — mirrors the billing/platform configs). With billing OFF
|
|
195
|
+
* there's no metering/enforcement surface, so the default tier is `unlimited`. */
|
|
196
|
+
export function isBillingEnabled() {
|
|
197
|
+
return (process.env.BILLING_ENABLED || 'true').toLowerCase() !== 'false';
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Default tier assigned to new organizations.
|
|
201
|
+
* - Billing DISABLED → `unlimited` (nothing is metered, so everything is uncapped).
|
|
202
|
+
* - Billing ENABLED → `DEFAULT_QUOTA_TIER` if it's a valid standard tier, else `developer`.
|
|
203
|
+
*/
|
|
204
|
+
export const DEFAULT_TIER = !isBillingEnabled()
|
|
205
|
+
? 'unlimited'
|
|
206
|
+
: (isValidTier(process.env.DEFAULT_QUOTA_TIER ?? '') && process.env.DEFAULT_QUOTA_TIER !== 'unlimited'
|
|
207
|
+
? process.env.DEFAULT_QUOTA_TIER
|
|
208
|
+
: 'developer');
|
|
209
|
+
/** Check whether a string is a valid QuotaTier. */
|
|
210
|
+
export function isValidTier(value) {
|
|
211
|
+
// Use the explicit tuple, not `value in QUOTA_TIERS`: `in` walks the prototype
|
|
212
|
+
// chain, so inherited Object keys ('toString', 'constructor', …) would return
|
|
213
|
+
// true and then `getTierLimits` would read `.limits` off a function → crash.
|
|
214
|
+
// `tier` is attacker-influenceable (JWT / request body / DEFAULT_QUOTA_TIER env).
|
|
215
|
+
return VALID_TIERS.includes(value);
|
|
216
|
+
}
|
|
217
|
+
/** Get the default limits for a given tier (falls back to developer). */
|
|
218
|
+
export function getTierLimits(tier) {
|
|
219
|
+
return isValidTier(tier) ? QUOTA_TIERS[tier].limits : QUOTA_TIERS.developer.limits;
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEtdGllcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvcXVvdGEtdGllcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQXVEdEM7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxFQUFFLEdBQUcsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFFOUI7Ozs7OztHQU1HO0FBQ0gsTUFBTSxtQkFBbUIsR0FBdUM7SUFDOUQsMEVBQTBFO0lBQzFFLDRFQUE0RTtJQUM1RSw4RUFBOEU7SUFDOUUsU0FBUyxFQUFFO1FBQ1QsT0FBTyxFQUFFLEVBQUU7UUFDWCxTQUFTLEVBQUUsQ0FBQztRQUNaLFFBQVEsRUFBRSxNQUFNO1FBQ2hCLE9BQU8sRUFBRSxFQUFFO1FBQ1gsWUFBWSxFQUFFLENBQUMsR0FBRyxFQUFFO1FBQ3BCLFVBQVUsRUFBRSxFQUFFO1FBQ2QsVUFBVSxFQUFFLEVBQUU7UUFDZCxpQkFBaUIsRUFBRSxFQUFFO1FBQ3JCLFVBQVUsRUFBRSxDQUFDO1FBQ2IsS0FBSyxFQUFFLENBQUM7UUFDUixrQkFBa0IsRUFBRSxFQUFFO1FBQ3RCLGlCQUFpQixFQUFFLEdBQUc7S0FDdkI7SUFDRCwrRUFBK0U7SUFDL0UsZ0ZBQWdGO0lBQ2hGLGdGQUFnRjtJQUNoRiw4RUFBOEU7SUFDOUUsR0FBRyxFQUFFO1FBQ0gsT0FBTyxFQUFFLEVBQUU7UUFDWCxTQUFTLEVBQUUsQ0FBQztRQUNaLFFBQVEsRUFBRSxPQUFPO1FBQ2pCLE9BQU8sRUFBRSxLQUFLO1FBQ2QsWUFBWSxFQUFFLEVBQUUsR0FBRyxFQUFFO1FBQ3JCLFVBQVUsRUFBRSxHQUFHO1FBQ2YsVUFBVSxFQUFFLEdBQUc7UUFDZixpQkFBaUIsRUFBRSxFQUFFO1FBQ3JCLFVBQVUsRUFBRSxDQUFDO1FBQ2IsS0FBSyxFQUFFLENBQUM7UUFDUixrQkFBa0IsRUFBRSxFQUFFO1FBQ3RCLGlCQUFpQixFQUFF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QUFRLFdBQWlDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzVELENBQUM7QUFFRCx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLGFBQWEsQ0FBQyxJQUFZO0lBQ3hDLE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFBLENBQUMsQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztBQUNwRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKiBBdmFpbGFibGUgcXVvdGEgdGllciBpZGVudGlmaWVycy5cbiAqXG4gKiBgdW5saW1pdGVkYCBpcyBhIHNwZWNpYWwgdGllcjogZXZlcnkgcXVvdGEgaXMgYC0xYCAodW5jYXBwZWQpIGFuZCBpdCBpbmNsdWRlc1xuICogZXZlcnkgZmVhdHVyZS9hZGQtb24gYnVuZGxlLiBJdCBpcyB0aGUgREVGQVVMVCB3aGVuIGJpbGxpbmcgaXMgZGlzYWJsZWQgKG5vXG4gKiBtZXRlcmluZy9lbmZvcmNlbWVudCBzdXJmYWNlIGV4aXN0cywgc28gbm90aGluZyBpcyBjYXBwZWQpLCBhbmQgaXQgaXMgTkVWRVJcbiAqIHNob3duIG9yIHNlbGVjdGFibGUgd2hlbiBiaWxsaW5nIGlzIGVuYWJsZWQg4oCUIHNlZSBgU1RBTkRBUkRfVElFUlNgLiAqL1xuZXhwb3J0IHR5cGUgUXVvdGFUaWVyID0gJ2RldmVsb3BlcicgfCAncHJvJyB8ICd0ZWFtJyB8ICdlbnRlcnByaXNlJyB8ICd1bmxpbWl0ZWQnO1xuXG4vKiogTGltaXQgdmFsdWVzIGZvciBlYWNoIHF1b3RhIHR5cGUgd2l0aGluIGEgdGllci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFUaWVyTGltaXRzIHtcbiAgcGx1Z2luczogbnVtYmVyO1xuICBwaXBlbGluZXM6IG51bWJlcjtcbiAgYXBpQ2FsbHM6IG51bWJlcjtcbiAgYWlDYWxsczogbnVtYmVyO1xuICAvKipcbiAgICogQWdncmVnYXRlIHJlZ2lzdHJ5IHN0b3JhZ2UgY2FwIGluIEJZVEVTLiBDb3VudGVkIGFjcm9zcyBldmVyeSByZXBvXG4gICAqIHVuZGVyIHRoZSBvcmcncyBgb3JnLXtvcmdJZH0vYCBuYW1lc3BhY2UuIC0xIG1lYW5zIHVubGltaXRlZC5cbiAgICogcHVzaC1nYXRlIHJlYWRzIHRoaXM7IHRoZSBpbWFnZS1yZWdpc3RyeSByZWplY3RzIHRva2VuIGlzc3VhbmNlIGZvclxuICAgKiBgcHVzaGAgc2NvcGUgd2hlbiB0aGUgb3JnJ3MgbWVhc3VyZWQgdXNhZ2UgZXhjZWVkcyB0aGUgbGltaXQuXG4gICAqL1xuICBzdG9yYWdlQnl0ZXM6IG51bWJlcjtcbiAgLyoqIENvdW50LXF1b3RhcyBvbiB0aGUgdXNlci1lZGl0YWJsZSBmZWF0dXJlIHRhYmxlcyBhZGRlZCB0byBjbG9zZSBwZXItb3JnXG4gICAqICBEb1MgdmlhIHNwYW0uIC0xIG1lYW5zIHVubGltaXRlZC4gKi9cbiAgZGFzaGJvYXJkczogbnVtYmVyO1xuICBhbGVydFJ1bGVzOiBudW1iZXI7XG4gIGFsZXJ0RGVzdGluYXRpb25zOiBudW1iZXI7XG4gIGlkcENvbmZpZ3M6IG51bWJlcjtcbiAgLyoqXG4gICAqIE1heCBvcmcgbWVtYmVycyAoYWN0aXZlIHVzZXJzIC8gc2VhdHMpLiAtMSA9IHVubGltaXRlZC4gVGhpcyBpcyB0aGUgXCJUZWFtXCJcbiAgICogdGllciBkaWZmZXJlbnRpYXRvciDigJQgZW5mb3JjZWQgYXQgbWVtYmVyLWludml0ZSB0aW1lIChhbiBpbnZpdGUgaXMgYmxvY2tlZFxuICAgKiB3aGVuIGFjdGl2ZSBtZW1iZXJzICsgcGVuZGluZyBpbnZpdGVzIHdvdWxkIGV4Y2VlZCB0aGlzKS5cbiAgICovXG4gIHNlYXRzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBSZXBvcnRpbmcgcmV0ZW50aW9uIGluIERBWVMg4oCUIE5PVCBhIGZsb3cgcXVvdGEgKG5ldmVyIGRlY3JlbWVudGVkLCBhYnNlbnRcbiAgICogZnJvbSBgVkFMSURfUVVPVEFfVFlQRVNgKTogdGhlc2UgcmlkZSB0aGUgdGllci1iYXNlbGluZSArIGJ1bmRsZS1ncmFudCBtYXRoXG4gICAqIHB1cmVseSBhcyBhbiBlbnRpdGxlbWVudCB0aGUgYmlsbGluZyBzZXJ2aWNlIHN5bmNzIHRvIHJlcG9ydGluZydzXG4gICAqIGBkb3JhX3NldHRpbmdzYC4gLTEgPSB1bmxpbWl0ZWQgKHRoZSBzd2VlcCBza2lwcyB0aGUgb3JnIGVudGlyZWx5KS5cbiAgICogICBgZXZlbnRSZXRlbnRpb25EYXlzYCDigJQgbm9uLWRlcGxveSBgcGlwZWxpbmVfZXZlbnRzYCAoU1RBR0UvQUNUSU9OL2J1aWxkKS5cbiAgICogICBgZG9yYVJldGVudGlvbkRheXNgICDigJQgZGVwbG95IGV2ZW50cyArIGBkZXBsb3ltZW50X291dGNvbWVzYCArIGBpbmNpZGVudHNgLFxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgYW5kIHRoZSBwZXItb3JnIHJlcG9ydC1xdWVyeSB3aW5kb3cgZm9yIERPUkEgcm91dGVzLlxuICAgKiBFeHRlbmRhYmxlIHZpYSB0aGUgYHJldGVudGlvbl9wYWNrYCAvIGBkb3JhX2hpc3RvcnlfcGFja2AgYWRkLW9uIGJ1bmRsZXMuXG4gICAqL1xuICBldmVudFJldGVudGlvbkRheXM6IG51bWJlcjtcbiAgZG9yYVJldGVudGlvbkRheXM6IG51bWJlcjtcbn1cblxuLyoqIEZ1bGwgcHJlc2V0IGZvciBhIHNpbmdsZSB0aWVyIChsYWJlbCArIGxpbWl0cykuICovXG5leHBvcnQgaW50ZXJmYWNlIFF1b3RhVGllclByZXNldCB7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIGxpbWl0czogUXVvdGFUaWVyTGltaXRzO1xufVxuXG4vKipcbiAqIFByZXNldCBsaW1pdHMgZm9yIGVhY2ggdGllci4gLTEgbWVhbnMgdW5saW1pdGVkLlxuICpcbiAqIEFJIGNhbGxzIGFyZSBzaXplZCBtdWNoIHNtYWxsZXIgdGhhbiBgYXBpQ2FsbHNgIGJlY2F1c2UgZWFjaCBjYWxsIGhhc1xuICogZXh0ZXJuYWwgcHJvdmlkZXIgY29zdCAofiQwLjAxJDAuMTAvY2FsbCkuIERldmVsb3BlciB0aWVyIGFsbG93cyBsaWdodFxuICogZXhwbG9yYXRpb24gKDUwL3BlcmlvZCk7IFBybyBsaWZ0cyB0byAyLDUwMDsgRW50ZXJwcmlzZSBpcyBjYXBwZWQgaGlnaFxuICogKDI1LDAwMCkg4oCUIGZhaXItdXNlLCBub3QgbGl0ZXJhbGx5IHVubGltaXRlZC5cbiAqXG4gKiBgc3RvcmFnZUJ5dGVzYCBpcyB0aGUgYWdncmVnYXRlIHJlZ2lzdHJ5IGNhcCBwZXIgb3JnLiBTaXplZFxuICogYXJvdW5kIHBsdWdpbi1pbWFnZSByZWFsaXRpZXM6IGEgdHlwaWNhbCBwbHVnaW4gaW1hZ2UgaXMgMjAwNTAwIE1CO1xuICogRGV2ZWxvcGVyJ3MgMiBHQiBob2xkcyB+NCB2ZXJzaW9ucyDDlyB+NTAwIE1CLCBQcm8ncyA1MCBHQiBjb3ZlcnMgYVxuICogbWF0dXJlIGNhdGFsb2cuIE9wZXJhdG9ycyBjYW4gb3ZlcnJpZGUgcGVyLW9yZyB2aWEgdGhlIHF1b3RhIENSVUQgQVBJLlxuICovXG5jb25zdCBHQiA9IDEwMjQgKiAxMDI0ICogMTAyNDtcblxuLyoqXG4gKiBDb2RlLWRlZmF1bHQgbGltaXRzIHBlciB0aWVyIOKAlCB0aGUgZmFsbGJhY2sgd2hlbiBubyBlbnYgb3ZlcnJpZGUgaXMgc2V0LlxuICogLTEgbWVhbnMgdW5saW1pdGVkLiAoQ291bnRzIHNpemVkIHRvIFwiY29tZm9ydGFibHkgZW5vdWdoIGZvciBvbmUgdGVhbSwgbm90XG4gKiBzY3JpcHQgc3BhbVwiOiAyMCBkYXNoYm9hcmRzLCA1MCBhbGVydCBydWxlcywgMTAgZGVzdGluYXRpb25zLCAxIElkUCBjb25maWdcbiAqIGZvciBEZXZlbG9wZXI7IHNjYWxlZCB1cCBmb3IgUHJvOyAtMSAodW5jYXBwZWQpIGZvciB0aGUgY2hlYXAgY291bnQtcXVvdGFzXG4gKiBvbiBUZWFtL0VudGVycHJpc2Ugd2hpbGUgY29zdC1kcml2aW5nIHF1b3RhcyDigJQgaW5jbC4gYXBpQ2FsbHMg4oCUIHN0YXkgZmluaXRlLilcbiAqL1xuY29uc3QgREVGQVVMVF9USUVSX0xJTUlUUzogUmVjb3JkPFF1b3RhVGllciwgUXVvdGFUaWVyTGltaXRzPiA9IHtcbiAgLy8gRnJlZSB0aWVyOiBzaW5nbGUgc2VhdCwgMiBwaXBlbGluZXMsIGFwaUNhbGxzIENBUFBFRCAod2FzIHVubGltaXRlZCDigJQgYVxuICAvLyBEb1MvYWJ1c2UgaG9sZSBvbiBhIHNoYXJlZCByZXNvdXJjZSk7IGFpQ2FsbHMgc21hbGwgKGVhY2ggaGFzIH4kMC4wMS0wLjEwXG4gIC8vIGV4dGVybmFsIGNvc3QpLiBMZWFuIGJhc2Ug4oCUIGdyb3d0aCBoYXBwZW5zIGJ5IHVwZ3JhZGluZywgbm90IHN0YWNraW5nIGhlcmUuXG4gIGRldmVsb3Blcjoge1xuICAgIHBsdWdpbnM6IDI1LFxuICAgIHBpcGVsaW5lczogMixcbiAgICBhcGlDYWxsczogMjVfMDAwLFxuICAgIGFpQ2FsbHM6IDI1LFxuICAgIHN0b3JhZ2VCeXRlczogMiAqIEdCLFxuICAgIGRhc2hib2FyZHM6IDIwLFxuICAgIGFsZXJ0UnVsZXM6IDUwLFxuICAgIGFsZXJ0RGVzdGluYXRpb25zOiAxMCxcbiAgICBpZHBDb25maWdzOiAxLFxuICAgIHNlYXRzOiAxLFxuICAgIGV2ZW50UmV0ZW50aW9uRGF5czogMzAsXG4gICAgZG9yYVJldGVudGlvbkRheXM6IDE4MCxcbiAgfSxcbiAgLy8gUHJvID0gaW5kaXZpZHVhbCBwb3dlciB1c2VyLCBzaW5nbGUgc2VhdCwgaW5kaXZpZHVhbCBwcmljaW5nLiBBIDJuZCBzZWF0IChvclxuICAvLyB0ZWFtIGNvbGxhYm9yYXRpb24pIHJlcXVpcmVzIHRoZSBUZWFtIHRpZXIg4oCUIHRoZSBgc2VhdGAgYWRkLW9uIGlzIFRlYW0rIG9ubHksXG4gIC8vIGtlZXBpbmcgVGVhbSB0aGUgY29sbGFib3JhdGlvbiB0aWVyLiBQcm8ncyB2YWx1ZSBvdmVyIERldmVsb3BlciBpcyBpdHMgcmljaGVyXG4gIC8vIGNhbGwvc3RvcmFnZS9wbHVnaW4gY2VpbGluZ3MgKyBmZWF0dXJlIGFkZC1vbnMgKFNTTy9hdWRpdC9ET1JBKSwgbm90IHNlYXRzLlxuICBwcm86IHtcbiAgICBwbHVnaW5zOiA1MCxcbiAgICBwaXBlbGluZXM6IDUsXG4gICAgYXBpQ2FsbHM6IDI1MF8wMDAsXG4gICAgYWlDYWxsczogMV8wMDAsXG4gICAgc3RvcmFnZUJ5dGVzOiAyNSAqIEdCLFxuICAgIGRhc2hib2FyZHM6IDIwMCxcbiAgICBhbGVydFJ1bGVzOiA1MDAsXG4gICAgYWxlcnREZXN0aW5hdGlvbnM6IDUwLFxuICAgIGlkcENvbmZpZ3M6IDUsXG4gICAgc2VhdHM6IDEsXG4gICAgZXZlbnRSZXRlbnRpb25EYXlzOiAzMCxcbiAgICBkb3JhUmV0ZW50aW9uRGF5czogMTgwLFxuICB9LFxuICAvLyBUZWFtID0gY29sbGFib3JhdGlvbiB0aWVyOyB0aGUgc2VhdCBsaW1pdCAoMykgaXMgdGhlIHJlYWwgZGlmZmVyZW50aWF0b3Igb3ZlclxuICAvLyBQcm8gKHNpbmdsZS1zZWF0KSDigJQgaXQncyB0aGUgbXVsdGktc2VhdCBjb2xsYWJvcmF0aW9uIGZsb29yLiBMZWFuIGJhc2UgKCQ3OSk6XG4gIC8vIGdyb3d0aCByaWRlcyB0aGUgc2VhdC9waXBlbGluZS9ldGMgYWRkLW9ucyAobGFuZC1hbmQtZXhwYW5kKS4gTGltaXRzIHNpdFxuICAvLyBiZXR3ZWVuIFBybyBhbmQgRW50ZXJwcmlzZS5cbiAgdGVhbToge1xuICAgIHBsdWdpbnM6IDc1LFxuICAgIHBpcGVsaW5lczogNixcbiAgICBhcGlDYWxsczogNTAwXzAwMCxcbiAgICBhaUNhbGxzOiAyXzUwMCxcbiAgICBzdG9yYWdlQnl0ZXM6IDYwICogR0IsXG4gICAgZGFzaGJvYXJkczogLTEsXG4gICAgYWxlcnRSdWxlczogLTEsXG4gICAgYWxlcnREZXN0aW5hdGlvbnM6IC0xLFxuICAgIGlkcENvbmZpZ3M6IDUsXG4gICAgc2VhdHM6IDMsXG4gICAgZXZlbnRSZXRlbnRpb25EYXlzOiAzMCxcbiAgICBkb3JhUmV0ZW50aW9uRGF5czogMTgwLFxuICB9LFxuICAvLyBFbnRlcnByaXNlICgkNTk5LCBoZWxkKTogdGhlIGFsbC1pbmNsdXNpdmUgdGllciDigJQgMTUgc2VhdHMsIDMwIHBpcGVsaW5lcywgQUxMXG4gIC8vIHByZW1pdW0gZmVhdHVyZXMgaW5jbHVkZWQgKHNlZSBUSUVSX0ZFQVRVUkVTKS4gRkFJUi1VU0Ug4oCUIGNvc3QgZHJpdmVycyAoYXBpQ2FsbHMsXG4gIC8vIGFpQ2FsbHMsIHN0b3JhZ2VCeXRlcykgY2FwcGVkIHNvIG9uZSBhY2NvdW50IGNhbid0IHJ1biB1cCB1bmJvdW5kZWRcbiAgLy8gY29tcHV0ZS9wcm92aWRlci9zdG9yYWdlIGNvc3Qgb24gYSBmbGF0IHByaWNlOyBjaGVhcCBjb3VudC1xdW90YXMgc3RheSAtMS5cbiAgZW50ZXJwcmlzZToge1xuICAgIHBsdWdpbnM6IDE1MCxcbiAgICBwaXBlbGluZXM6IDMwLFxuICAgIGFwaUNhbGxzOiA5MDBfMDAwLFxuICAgIGFpQ2FsbHM6IDlfMDAwLFxuICAgIHN0b3JhZ2VCeXRlczogMjUwICogR0IsXG4gICAgZGFzaGJvYXJkczogLTEsXG4gICAgYWxlcnRSdWxlczogLTEsXG4gICAgYWxlcnREZXN0aW5hdGlvbnM6IC0xLFxuICAgIGlkcENvbmZpZ3M6IC0xLFxuICAgIHNlYXRzOiAxNSxcbiAgICBldmVudFJldGVudGlvbkRheXM6IDMwLFxuICAgIGRvcmFSZXRlbnRpb25EYXlzOiAxODAsXG4gIH0sXG4gIC8vIFVubGltaXRlZDogRVZFUlkgcXVvdGEgdW5jYXBwZWQgKC0xKS4gVGhlIGRlZmF1bHQgd2hlbiBiaWxsaW5nIGlzIGRpc2FibGVkXG4gIC8vIChubyBlbmZvcmNlbWVudCBzdXJmYWNlKSDigJQgbmV2ZXIgc2hvd24vc2VsZWN0YWJsZSB3aGVuIGJpbGxpbmcgaXMgZW5hYmxlZC5cbiAgdW5saW1pdGVkOiB7XG4gICAgcGx1Z2luczogLTEsXG4gICAgcGlwZWxpbmVzOiAtMSxcbiAgICBhcGlDYWxsczogLTEsXG4gICAgYWlDYWxsczogLTEsXG4gICAgc3RvcmFnZUJ5dGVzOiAtMSxcbiAgICBkYXNoYm9hcmRzOiAtMSxcbiAgICBhbGVydFJ1bGVzOiAtMSxcbiAgICBhbGVydERlc3RpbmF0aW9uczogLTEsXG4gICAgaWRwQ29uZmlnczogLTEsXG4gICAgc2VhdHM6IC0xLFxuICAgIGV2ZW50UmV0ZW50aW9uRGF5czogLTEsXG4gICAgZG9yYVJldGVudGlvbkRheXM6IC0xLFxuICB9LFxufTtcblxuLyoqXG4gKiBSZWFkIGFuIGludGVnZXIgZW52IHZhciwgZmFsbGluZyBiYWNrIHRvIHRoZSBjb2RlIGRlZmF1bHQuIGAtMWAgPSB1bmxpbWl0ZWQuXG4gKiBSZWplY3RzICjihpIgZmFsbGJhY2spIGFueXRoaW5nIHRoYXQgaXNuJ3QgYSBjbGVhbiBpbnRlZ2VyIHN0cmluZyBhbmQgYW55IHZhbHVlXG4gKiBgPCAtMWA6IGEgZGVjaW1hbCAoYDUwLjVgKSBvciBhIG5vbnNlbnNlIG5lZ2F0aXZlIChgLTVgKSB3b3VsZCBvdGhlcndpc2Ugc2hpcCBhXG4gKiBicm9rZW4gZmluaXRlIGxpbWl0IChwYXJpdHkgd2l0aCBgZW52Q2VudHNgJ3Mgcmlnb3IgZm9yIHByaWNlcykuXG4gKi9cbmZ1bmN0aW9uIGVudkludChuYW1lOiBzdHJpbmcsIGZhbGxiYWNrOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudltuYW1lXTtcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gJycpIHJldHVybiBmYWxsYmFjaztcbiAgY29uc3QgdHJpbW1lZCA9IHJhdy50cmltKCk7XG4gIGlmICghL14tP1xcZCskLy50ZXN0KHRyaW1tZWQpKSByZXR1cm4gZmFsbGJhY2s7IC8vIG5vIGRlY2ltYWxzIC8gbm9uLW51bWVyaWNcbiAgY29uc3QgbiA9IHBhcnNlSW50KHRyaW1tZWQsIDEwKTtcbiAgcmV0dXJuIE51bWJlci5pc05hTihuKSB8fCBuIDwgLTEgPyBmYWxsYmFjayA6IG47XG59XG5cbi8qKiBSZWFkIGEgc3RyaW5nIGVudiB2YXIsIGZhbGxpbmcgYmFjayB0byB0aGUgY29kZSBkZWZhdWx0LiAqL1xuZnVuY3Rpb24gZW52U3RyKG5hbWU6IHN0cmluZywgZmFsbGJhY2s6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52W25hbWVdO1xuICByZXR1cm4gcmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSAnJyA/IGZhbGxiYWNrIDogcmF3O1xufVxuXG4vKipcbiAqIFBlci10aWVyIGxpbWl0cywgZWFjaCBvdmVycmlkYWJsZSB2aWEgYFFVT1RBX1RJRVJfPFRJRVI+XzxMSU1JVD5gIGVudiB2YXJzXG4gKiAoZS5nLiBgUVVPVEFfVElFUl9QUk9fUElQRUxJTkVTPTI1MGAsIGBRVU9UQV9USUVSX0RFVkVMT1BFUl9TVE9SQUdFX0JZVEVTPS4uLmApLlxuICogVW5zZXQvZW1wdHkg4oaSIHRoZSBjb2RlIGRlZmF1bHQuIGAtMWAgPSB1bmxpbWl0ZWQuIFJlYWQgb25jZSBhdCBtb2R1bGUgbG9hZCDigJRcbiAqIG9uIGs4cyB0aGVzZSBmbG93IGluIHZpYSB0aGUgYGFwcC1lbnZgIENvbmZpZ01hcCAoYnVpbHQgZnJvbSBgLmVudmApLlxuICovXG5mdW5jdGlvbiB0aWVyTGltaXRzKHRpZXI6IFF1b3RhVGllcik6IFF1b3RhVGllckxpbWl0cyB7XG4gIC8vIGB1bmxpbWl0ZWRgIGlzIHVuY2FwcGVkIEJZIERFRklOSVRJT046IEVWRVJZIHF1b3RhIGlzIC0xIGFuZCBpdCBpcyBOT1RcbiAgLy8gZW52LW92ZXJyaWRhYmxlLiBSZWFkaW5nIFFVT1RBX1RJRVJfVU5MSU1JVEVEXyogaGVyZSB3b3VsZCBsZXQgYSBzdHJheSBlbnZcbiAgLy8gdmFyIHNpbGVudGx5IGNhcCB0aGUgYmlsbGluZy1ESVNBQkxFRCBkZWZhdWx0IHRpZXIg4oCUIHN1cmZhY2luZyBhcyBhIHNwdXJpb3VzXG4gIC8vIFwicXVvdGEgZXhjZWVkZWRcIiBvbiBhIGRlcGxveSB0aGF0IG1ldGVycyBub3RoaW5nLiBEZXJpdmUgLTEgZm9yIGV2ZXJ5IGZpZWxkXG4gIC8vIGZyb20gdGhlIGxpbWl0cyBzaGFwZSBzbyBhIG5ld2x5LWFkZGVkIHF1b3RhIGlzIHVuY2FwcGVkIGhlcmUgYXV0b21hdGljYWxseS5cbiAgaWYgKHRpZXIgPT09ICd1bmxpbWl0ZWQnKSB7XG4gICAgY29uc3QgdW5jYXBwZWQgPSB7IC4uLkRFRkFVTFRfVElFUl9MSU1JVFMudW5saW1pdGVkIH07XG4gICAgZm9yIChjb25zdCBrIG9mIE9iamVjdC5rZXlzKHVuY2FwcGVkKSBhcyAoa2V5b2YgUXVvdGFUaWVyTGltaXRzKVtdKSB1bmNhcHBlZFtrXSA9IC0xO1xuICAgIHJldHVybiB1bmNhcHBlZDtcbiAgfVxuICBjb25zdCBkID0gREVGQVVMVF9USUVSX0xJTUlUU1t0aWVyXTtcbiAgY29uc3QgVCA9IHRpZXIudG9VcHBlckNhc2UoKTtcbiAgcmV0dXJuIHtcbiAgICBwbHVnaW5zOiBlbnZJbnQoYFFVT1RBX1RJRVJfJHtUfV9QTFVHSU5TYCwgZC5wbHVnaW5zKSxcbiAgICBwaXBlbGluZXM6IGVudkludChgUVVPVEFfVElFUl8ke1R9X1BJUEVMSU5FU2AsIGQucGlwZWxpbmVzKSxcbiAgICBhcGlDYWxsczogZW52SW50KGBRVU9UQV9USUVSXyR7VH1fQVBJX0NBTExTYCwgZC5hcGlDYWxscyksXG4gICAgYWlDYWxsczogZW52SW50KGBRVU9UQV9USUVSXyR7VH1fQUlfQ0FMTFNgLCBkLmFpQ2FsbHMpLFxuICAgIHN0b3JhZ2VCeXRlczogZW52SW50KGBRVU9UQV9USUVSXyR7VH1fU1RPUkFHRV9CWVRFU2AsIGQuc3RvcmFnZUJ5dGVzKSxcbiAgICBkYXNoYm9hcmRzOiBlbnZJbnQoYFFVT1RBX1RJRVJfJHtUfV9EQVNIQk9BUkRTYCwgZC5kYXNoYm9hcmRzKSxcbiAgICBhbGVydFJ1bGVzOiBlbnZJbnQoYFFVT1RBX1RJRVJfJHtUfV9BTEVSVF9SVUxFU2AsIGQuYWxlcnRSdWxlcyksXG4gICAgYWxlcnREZXN0aW5hdGlvbnM6IGVudkludChgUVVPVEFfVElFUl8ke1R9X0FMRVJUX0RFU1RJTkFUSU9OU2AsIGQuYWxlcnREZXN0aW5hdGlvbnMpLFxuICAgIGlkcENvbmZpZ3M6IGVudkludChgUVVPVEFfVElFUl8ke1R9X0lEUF9DT05GSUdTYCwgZC5pZHBDb25maWdzKSxcbiAgICBzZWF0czogZW52SW50KGBRVU9UQV9USUVSXyR7VH1fU0VBVFNgLCBkLnNlYXRzKSxcbiAgICBldmVudFJldGVudGlvbkRheXM6IGVudkludChgUVVPVEFfVElFUl8ke1R9X0VWRU5UX1JFVEVOVElPTl9EQVlTYCwgZC5ldmVudFJldGVudGlvbkRheXMpLFxuICAgIGRvcmFSZXRlbnRpb25EYXlzOiBlbnZJbnQoYFFVT1RBX1RJRVJfJHtUfV9ET1JBX1JFVEVOVElPTl9EQVlTYCwgZC5kb3JhUmV0ZW50aW9uRGF5cyksXG4gIH07XG59XG5cbi8vIExhYmVscyBhcmUgb3ZlcnJpZGFibGUgdmlhIGBRVU9UQV9USUVSXzxUSUVSPl9MQUJFTGAgKGRpc3BsYXkgbmFtZSBvbmx5KS5cbmV4cG9ydCBjb25zdCBRVU9UQV9USUVSUzogUmVjb3JkPFF1b3RhVGllciwgUXVvdGFUaWVyUHJlc2V0PiA9IHtcbiAgZGV2ZWxvcGVyOiB7IGxhYmVsOiBlbnZTdHIoJ1FVT1RBX1RJRVJfREVWRUxPUEVSX0xBQkVMJywgJ0RldmVsb3BlcicpLCBsaW1pdHM6IHRpZXJMaW1pdHMoJ2RldmVsb3BlcicpIH0sXG4gIHBybzogeyBsYWJlbDogZW52U3RyKCdRVU9UQV9USUVSX1BST19MQUJFTCcsICdQcm8nKSwgbGltaXRzOiB0aWVyTGltaXRzKCdwcm8nKSB9LFxuICB0ZWFtOiB7IGxhYmVsOiBlbnZTdHIoJ1FVT1RBX1RJRVJfVEVBTV9MQUJFTCcsICdUZWFtJyksIGxpbWl0czogdGllckxpbWl0cygndGVhbScpIH0sXG4gIGVudGVycHJpc2U6IHsgbGFiZWw6IGVudlN0cignUVVPVEFfVElFUl9FTlRFUlBSSVNFX0xBQkVMJywgJ0VudGVycHJpc2UnKSwgbGltaXRzOiB0aWVyTGltaXRzKCdlbnRlcnByaXNlJykgfSxcbiAgdW5saW1pdGVkOiB7IGxhYmVsOiBlbnZTdHIoJ1FVT1RBX1RJRVJfVU5MSU1JVEVEX0xBQkVMJywgJ1VubGltaXRlZCcpLCBsaW1pdHM6IHRpZXJMaW1pdHMoJ3VubGltaXRlZCcpIH0sXG59O1xuXG4vKiogQWxsIHZhbGlkIHRpZXIgbmFtZXMgKGluY2wuIGB1bmxpbWl0ZWRgKS4gVXNlZCBmb3IgdmFsaWRhdGlvbiBvZiBhICpzdG9yZWQqXG4gKiAgdGllciDigJQgYHVubGltaXRlZGAgaXMgYSB2YWxpZCB2YWx1ZSBldmVuIHRob3VnaCBpdCdzIG5ldmVyIG9mZmVyZWQgZm9yIHNhbGUuICovXG5leHBvcnQgY29uc3QgVkFMSURfVElFUlM6IHJlYWRvbmx5IFF1b3RhVGllcltdID0gT2JqZWN0LmtleXMoUVVPVEFfVElFUlMpIGFzIFF1b3RhVGllcltdO1xuXG4vKiogVGhlIHN0YW5kYXJkLCBiaWxsaW5nLXNlbGVjdGFibGUgdGllcnMg4oCUIHRoZSBvbmVzIG9mZmVyZWQgYXMgcHVyY2hhc2FibGUgcGxhbnNcbiAqICBhbmQgc2hvd24gaW4gdGllciBwaWNrZXJzLiBEZXJpdmVkIGFzIFwiZXZlcnkgdmFsaWQgdGllciBleGNlcHQgYHVubGltaXRlZGBcIixcbiAqICB3aGljaCBpcyB0aGUgYmlsbGluZy1ESVNBQkxFRCBkZWZhdWx0IGFuZCBpcyBuZXZlciBkaXNwbGF5ZWQvc2VsZWN0YWJsZSB3aGVuXG4gKiAgYmlsbGluZyBpcyBlbmFibGVkLiBLZXB0IERSWSBvZmYgYFZBTElEX1RJRVJTYCBzbyBhZGRpbmcgYSB0aWVyIGZsb3dzIHRocm91Z2guICovXG5leHBvcnQgY29uc3QgU1RBTkRBUkRfVElFUlM6IHJlYWRvbmx5IFF1b3RhVGllcltdID0gVkFMSURfVElFUlMuZmlsdGVyKCh0KSA9PiB0ICE9PSAndW5saW1pdGVkJyk7XG5cbi8qKiBUaWVycyB0aGF0IHBlcm1pdCB0aGUgb3JnIOKGkiB0ZWFtIGhpZXJhcmNoeSAobmVzdGluZyB0ZWFtcyB1bmRlciBhIHJvb3QpLiBUaGVcbiAqICBiaWxsaW5nLW9mZiBgdW5saW1pdGVkYCB0aWVyIGlzIHRlYW0tY2FwYWJsZSAoaXQncyB0aGUgbW9zdCBwZXJtaXNzaXZlKTsgdGhlXG4gKiAgZW50cnktbGV2ZWwgYGRldmVsb3BlcmAvYHByb2AgdGllcnMgYXJlIG5vdC4gU2luZ2xlIHNvdXJjZSBmb3IgdGhlIHBhcmVudC1cbiAqICBlbGlnaWJpbGl0eSArIGRvd25ncmFkZS1vdmVyY2FwIGNoZWNrcyBzbyB0aGV5IGNhbid0IGRyaWZ0LiAqL1xuZXhwb3J0IGNvbnN0IFRFQU1fQ0FQQUJMRV9USUVSUzogcmVhZG9ubHkgUXVvdGFUaWVyW10gPSBbJ3RlYW0nLCAnZW50ZXJwcmlzZScsICd1bmxpbWl0ZWQnXTtcbmV4cG9ydCBmdW5jdGlvbiB0aWVyQWxsb3dzVGVhbXModGllcjogc3RyaW5nIHwgdW5kZWZpbmVkIHwgbnVsbCk6IGJvb2xlYW4ge1xuICByZXR1cm4gISF0aWVyICYmIChURUFNX0NBUEFCTEVfVElFUlMgYXMgcmVhZG9ubHkgc3RyaW5nW10pLmluY2x1ZGVzKHRpZXIpO1xufVxuXG4vKiogV2hldGhlciB0aGUgYmlsbGluZyBzZXJ2aWNlIGlzIGVuYWJsZWQgaW4gdGhpcyBkZXBsb3ltZW50IChgQklMTElOR19FTkFCTEVEYCxcbiAqICBvcHQtb3V0IGRlZmF1bHQtb24g4oCUIG1pcnJvcnMgdGhlIGJpbGxpbmcvcGxhdGZvcm0gY29uZmlncykuIFdpdGggYmlsbGluZyBPRkZcbiAqICB0aGVyZSdzIG5vIG1ldGVyaW5nL2VuZm9yY2VtZW50IHN1cmZhY2UsIHNvIHRoZSBkZWZhdWx0IHRpZXIgaXMgYHVubGltaXRlZGAuICovXG5leHBvcnQgZnVuY3Rpb24gaXNCaWxsaW5nRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgcmV0dXJuIChwcm9jZXNzLmVudi5CSUxMSU5HX0VOQUJMRUQgfHwgJ3RydWUnKS50b0xvd2VyQ2FzZSgpICE9PSAnZmFsc2UnO1xufVxuXG4vKipcbiAqIERlZmF1bHQgdGllciBhc3NpZ25lZCB0byBuZXcgb3JnYW5pemF0aW9ucy5cbiAqIC0gQmlsbGluZyBESVNBQkxFRCDihpIgYHVubGltaXRlZGAgKG5vdGhpbmcgaXMgbWV0ZXJlZCwgc28gZXZlcnl0aGluZyBpcyB1bmNhcHBlZCkuXG4gKiAtIEJpbGxpbmcgRU5BQkxFRCAg4oaSIGBERUZBVUxUX1FVT1RBX1RJRVJgIGlmIGl0J3MgYSB2YWxpZCBzdGFuZGFyZCB0aWVyLCBlbHNlIGBkZXZlbG9wZXJgLlxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9USUVSOiBRdW90YVRpZXIgPSAhaXNCaWxsaW5nRW5hYmxlZCgpXG4gID8gJ3VubGltaXRlZCdcbiAgOiAoaXNWYWxpZFRpZXIocHJvY2Vzcy5lbnYuREVGQVVMVF9RVU9UQV9USUVSID8/ICcnKSAmJiBwcm9jZXNzLmVudi5ERUZBVUxUX1FVT1RBX1RJRVIgIT09ICd1bmxpbWl0ZWQnXG4gICAgPyAocHJvY2Vzcy5lbnYuREVGQVVMVF9RVU9UQV9USUVSIGFzIFF1b3RhVGllcilcbiAgICA6ICdkZXZlbG9wZXInKTtcblxuLyoqIENoZWNrIHdoZXRoZXIgYSBzdHJpbmcgaXMgYSB2YWxpZCBRdW90YVRpZXIuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFRpZXIodmFsdWU6IHN0cmluZyk6IHZhbHVlIGlzIFF1b3RhVGllciB7XG4gIC8vIFVzZSB0aGUgZXhwbGljaXQgdHVwbGUsIG5vdCBgdmFsdWUgaW4gUVVPVEFfVElFUlNgOiBgaW5gIHdhbGtzIHRoZSBwcm90b3R5cGVcbiAgLy8gY2hhaW4sIHNvIGluaGVyaXRlZCBPYmplY3Qga2V5cyAoJ3RvU3RyaW5nJywgJ2NvbnN0cnVjdG9yJywg4oCmKSB3b3VsZCByZXR1cm5cbiAgLy8gdHJ1ZSBhbmQgdGhlbiBgZ2V0VGllckxpbWl0c2Agd291bGQgcmVhZCBgLmxpbWl0c2Agb2ZmIGEgZnVuY3Rpb24g4oaSIGNyYXNoLlxuICAvLyBgdGllcmAgaXMgYXR0YWNrZXItaW5mbHVlbmNlYWJsZSAoSldUIC8gcmVxdWVzdCBib2R5IC8gREVGQVVMVF9RVU9UQV9USUVSIGVudikuXG4gIHJldHVybiAoVkFMSURfVElFUlMgYXMgcmVhZG9ubHkgc3RyaW5nW10pLmluY2x1ZGVzKHZhbHVlKTtcbn1cblxuLyoqIEdldCB0aGUgZGVmYXVsdCBsaW1pdHMgZm9yIGEgZ2l2ZW4gdGllciAoZmFsbHMgYmFjayB0byBkZXZlbG9wZXIpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRpZXJMaW1pdHModGllcjogc3RyaW5nKTogUXVvdGFUaWVyTGltaXRzIHtcbiAgcmV0dXJuIGlzVmFsaWRUaWVyKHRpZXIpID8gUVVPVEFfVElFUlNbdGllcl0ubGltaXRzOiBRVU9UQV9USUVSUy5kZXZlbG9wZXIubGltaXRzO1xufVxuIl19
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single sharing model for every catalog entity: pipelines, plugins,
|
|
3
|
+
* pipeline templates, and dashboards.
|
|
4
|
+
*
|
|
5
|
+
* Three rungs, widening left to right:
|
|
6
|
+
*
|
|
7
|
+
* - `private` — only the AUTHOR (`createdBy`) can see or edit it. A personal
|
|
8
|
+
* draft: somewhere to iterate before anyone else is affected.
|
|
9
|
+
* - `org` — everyone in the owning org can see it; the resource's `:write`
|
|
10
|
+
* permission edits it. This is the default working state for shared content.
|
|
11
|
+
* - `public` — shared beyond the org: a team also sees its parent org's public
|
|
12
|
+
* rows, and the system org's public rows are the shared catalog every org
|
|
13
|
+
* sees. Requires the resource's `:publish` permission.
|
|
14
|
+
*
|
|
15
|
+
* Enforcement lives in exactly two places, so no entity can drift:
|
|
16
|
+
* `AccessControlQueryBuilder` builds the read predicate, and
|
|
17
|
+
* `requireVisibilityWriteAccess` gates the writes.
|
|
18
|
+
*/
|
|
19
|
+
export declare const VISIBILITIES: readonly ['private', 'org', 'public'];
|
|
20
|
+
export type Visibility = (typeof VISIBILITIES)[number];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* The single sharing model for every catalog entity: pipelines, plugins,
|
|
5
|
+
* pipeline templates, and dashboards.
|
|
6
|
+
*
|
|
7
|
+
* Three rungs, widening left to right:
|
|
8
|
+
*
|
|
9
|
+
* - `private` — only the AUTHOR (`createdBy`) can see or edit it. A personal
|
|
10
|
+
* draft: somewhere to iterate before anyone else is affected.
|
|
11
|
+
* - `org` — everyone in the owning org can see it; the resource's `:write`
|
|
12
|
+
* permission edits it. This is the default working state for shared content.
|
|
13
|
+
* - `public` — shared beyond the org: a team also sees its parent org's public
|
|
14
|
+
* rows, and the system org's public rows are the shared catalog every org
|
|
15
|
+
* sees. Requires the resource's `:publish` permission.
|
|
16
|
+
*
|
|
17
|
+
* Enforcement lives in exactly two places, so no entity can drift:
|
|
18
|
+
* `AccessControlQueryBuilder` builds the read predicate, and
|
|
19
|
+
* `requireVisibilityWriteAccess` gates the writes.
|
|
20
|
+
*/
|
|
21
|
+
export const VISIBILITIES = ['private', 'org', 'public'];
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzaWJpbGl0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy92aXNpYmlsaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLENBQUMsU0FBUyxFQUFFLEtBQUssRUFBRSxRQUFRLENBQVUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFRoZSBzaW5nbGUgc2hhcmluZyBtb2RlbCBmb3IgZXZlcnkgY2F0YWxvZyBlbnRpdHk6IHBpcGVsaW5lcywgcGx1Z2lucyxcbiAqIHBpcGVsaW5lIHRlbXBsYXRlcywgYW5kIGRhc2hib2FyZHMuXG4gKlxuICogVGhyZWUgcnVuZ3MsIHdpZGVuaW5nIGxlZnQgdG8gcmlnaHQ6XG4gKlxuICogLSBgcHJpdmF0ZWAg4oCUIG9ubHkgdGhlIEFVVEhPUiAoYGNyZWF0ZWRCeWApIGNhbiBzZWUgb3IgZWRpdCBpdC4gQSBwZXJzb25hbFxuICogICBkcmFmdDogc29tZXdoZXJlIHRvIGl0ZXJhdGUgYmVmb3JlIGFueW9uZSBlbHNlIGlzIGFmZmVjdGVkLlxuICogLSBgb3JnYCAgICAg4oCUIGV2ZXJ5b25lIGluIHRoZSBvd25pbmcgb3JnIGNhbiBzZWUgaXQ7IHRoZSByZXNvdXJjZSdzIGA6d3JpdGVgXG4gKiAgIHBlcm1pc3Npb24gZWRpdHMgaXQuIFRoaXMgaXMgdGhlIGRlZmF1bHQgd29ya2luZyBzdGF0ZSBmb3Igc2hhcmVkIGNvbnRlbnQuXG4gKiAtIGBwdWJsaWNgICDigJQgc2hhcmVkIGJleW9uZCB0aGUgb3JnOiBhIHRlYW0gYWxzbyBzZWVzIGl0cyBwYXJlbnQgb3JnJ3MgcHVibGljXG4gKiAgIHJvd3MsIGFuZCB0aGUgc3lzdGVtIG9yZydzIHB1YmxpYyByb3dzIGFyZSB0aGUgc2hhcmVkIGNhdGFsb2cgZXZlcnkgb3JnXG4gKiAgIHNlZXMuIFJlcXVpcmVzIHRoZSByZXNvdXJjZSdzIGA6cHVibGlzaGAgcGVybWlzc2lvbi5cbiAqXG4gKiBFbmZvcmNlbWVudCBsaXZlcyBpbiBleGFjdGx5IHR3byBwbGFjZXMsIHNvIG5vIGVudGl0eSBjYW4gZHJpZnQ6XG4gKiBgQWNjZXNzQ29udHJvbFF1ZXJ5QnVpbGRlcmAgYnVpbGRzIHRoZSByZWFkIHByZWRpY2F0ZSwgYW5kXG4gKiBgcmVxdWlyZVZpc2liaWxpdHlXcml0ZUFjY2Vzc2AgZ2F0ZXMgdGhlIHdyaXRlcy5cbiAqL1xuZXhwb3J0IGNvbnN0IFZJU0lCSUxJVElFUyA9IFsncHJpdmF0ZScsICdvcmcnLCAncHVibGljJ10gYXMgY29uc3Q7XG5leHBvcnQgdHlwZSBWaXNpYmlsaXR5ID0gKHR5cGVvZiBWSVNJQklMSVRJRVMpW251bWJlcl07XG4iXX0=
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clear the memoized alias set so the next access re-reads `SUPPORT_ALIASES`.
|
|
3
|
+
* The cache is process-lifetime by design (env is fixed per process); this hook
|
|
4
|
+
* exists so tests can vary the env between cases.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resetSupportAliasesCache(): void;
|
|
7
|
+
/** Well-known fallback support alias used when SUPPORT_ALIASES is unconfigured. */
|
|
8
|
+
export declare const DEFAULT_SUPPORT_ALIAS = "support@pipeline-builder";
|
|
9
|
+
/**
|
|
10
|
+
* The PRIMARY (first-configured) support alias — for display / prefill in UIs
|
|
11
|
+
* (e.g. the compose "To" field), so the shown value is driven by SUPPORT_ALIASES
|
|
12
|
+
* rather than hardcoded. Falls back to {@link DEFAULT_SUPPORT_ALIAS} when the env
|
|
13
|
+
* is unset. (All configured aliases still resolve via {@link resolveRecipientAlias}.)
|
|
14
|
+
*/
|
|
15
|
+
export declare function getPrimarySupportAlias(): string;
|
|
16
|
+
/**
|
|
17
|
+
* ALL configured support aliases (order preserved), for UIs that surface every
|
|
18
|
+
* support inbox as a distinct recipient suggestion. Falls back to a single
|
|
19
|
+
* {@link DEFAULT_SUPPORT_ALIAS} when SUPPORT_ALIASES is unset.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getAllSupportAliases(): string[];
|
|
22
|
+
/** Result of alias resolution. */
|
|
23
|
+
export interface AliasResolution {
|
|
24
|
+
/** The resolved organization ID (e.g., 'system'). */
|
|
25
|
+
resolvedOrgId: string;
|
|
26
|
+
/** Whether the input was an alias that got resolved. */
|
|
27
|
+
wasAlias: boolean;
|
|
28
|
+
/** The original input value, useful for audit logging. */
|
|
29
|
+
originalValue: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve an email-like alias to an actual organization ID.
|
|
33
|
+
*
|
|
34
|
+
* If the input matches a configured support alias, it resolves to the system
|
|
35
|
+
* org ID. Otherwise the input is returned as-is (lowercased).
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveRecipientAlias(recipientOrgId: string): AliasResolution;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { SYSTEM_ORG_ID } from '../middleware/auth.js';
|
|
4
|
+
/** Lazily-cached set of support aliases, parsed from SUPPORT_ALIASES on first access. */
|
|
5
|
+
let _supportAliases;
|
|
6
|
+
function getSupportAliases() {
|
|
7
|
+
if (!_supportAliases) {
|
|
8
|
+
const raw = process.env.SUPPORT_ALIASES || '';
|
|
9
|
+
_supportAliases = new Set(raw
|
|
10
|
+
.split(',')
|
|
11
|
+
.map(alias => alias.trim().toLowerCase())
|
|
12
|
+
.filter(alias => alias.length > 0));
|
|
13
|
+
}
|
|
14
|
+
return _supportAliases;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Clear the memoized alias set so the next access re-reads `SUPPORT_ALIASES`.
|
|
18
|
+
* The cache is process-lifetime by design (env is fixed per process); this hook
|
|
19
|
+
* exists so tests can vary the env between cases.
|
|
20
|
+
*/
|
|
21
|
+
export function resetSupportAliasesCache() {
|
|
22
|
+
_supportAliases = undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Well-known fallback support alias used when SUPPORT_ALIASES is unconfigured. */
|
|
25
|
+
export const DEFAULT_SUPPORT_ALIAS = 'support@pipeline-builder';
|
|
26
|
+
/**
|
|
27
|
+
* The PRIMARY (first-configured) support alias — for display / prefill in UIs
|
|
28
|
+
* (e.g. the compose "To" field), so the shown value is driven by SUPPORT_ALIASES
|
|
29
|
+
* rather than hardcoded. Falls back to {@link DEFAULT_SUPPORT_ALIAS} when the env
|
|
30
|
+
* is unset. (All configured aliases still resolve via {@link resolveRecipientAlias}.)
|
|
31
|
+
*/
|
|
32
|
+
export function getPrimarySupportAlias() {
|
|
33
|
+
for (const alias of getSupportAliases())
|
|
34
|
+
return alias;
|
|
35
|
+
return DEFAULT_SUPPORT_ALIAS;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* ALL configured support aliases (order preserved), for UIs that surface every
|
|
39
|
+
* support inbox as a distinct recipient suggestion. Falls back to a single
|
|
40
|
+
* {@link DEFAULT_SUPPORT_ALIAS} when SUPPORT_ALIASES is unset.
|
|
41
|
+
*/
|
|
42
|
+
export function getAllSupportAliases() {
|
|
43
|
+
const all = [...getSupportAliases()];
|
|
44
|
+
return all.length > 0 ? all : [DEFAULT_SUPPORT_ALIAS];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve an email-like alias to an actual organization ID.
|
|
48
|
+
*
|
|
49
|
+
* If the input matches a configured support alias, it resolves to the system
|
|
50
|
+
* org ID. Otherwise the input is returned as-is (lowercased).
|
|
51
|
+
*/
|
|
52
|
+
export function resolveRecipientAlias(recipientOrgId) {
|
|
53
|
+
const normalized = recipientOrgId.trim().toLowerCase();
|
|
54
|
+
const aliases = getSupportAliases();
|
|
55
|
+
if (aliases.has(normalized)) {
|
|
56
|
+
return {
|
|
57
|
+
resolvedOrgId: SYSTEM_ORG_ID,
|
|
58
|
+
wasAlias: true,
|
|
59
|
+
originalValue: recipientOrgId,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
resolvedOrgId: normalized,
|
|
64
|
+
wasAlias: false,
|
|
65
|
+
originalValue: recipientOrgId,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxpYXMtcmVzb2x2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvYWxpYXMtcmVzb2x2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFdEQseUZBQXlGO0FBQ3pGLElBQUksZUFBd0MsQ0FBQztBQUU3QyxTQUFTLGlCQUFpQjtJQUN4QixJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDckIsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLElBQUksRUFBRSxDQUFDO1FBQzlDLGVBQWUsR0FBRyxJQUFJLEdBQUcsQ0FDdkIsR0FBRzthQUNBLEtBQUssQ0FBQyxHQUFHLENBQUM7YUFDVixHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7YUFDeEMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FDckMsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLGVBQWUsQ0FBQztBQUN6QixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSx3QkFBd0I7SUFDdEMsZUFBZSxHQUFHLFNBQVMsQ0FBQztBQUM5QixDQUFDO0FBRUQsbUZBQW1GO0FBQ25GLE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLDBCQUEwQixDQUFDO0FBRWhFOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQjtJQUNwQyxLQUFLLE1BQU0sS0FBSyxJQUFJLGlCQUFpQixFQUFFO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDdEQsT0FBTyxxQkFBcUIsQ0FBQztBQUMvQixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxvQkFBb0I7SUFDbEMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxHQUFHLGlCQUFpQixFQUFFLENBQUMsQ0FBQztJQUNyQyxPQUFPLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMscUJBQXFCLENBQUMsQ0FBQztBQUN4RCxDQUFDO0FBWUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQUMsY0FBc0I7SUFDMUQsTUFBTSxVQUFVLEdBQUcsY0FBYyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3ZELE1BQU0sT0FBTyxHQUFHLGlCQUFpQixFQUFFLENBQUM7SUFFcEMsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDNUIsT0FBTztZQUNMLGFBQWEsRUFBRSxhQUFhO1lBQzVCLFFBQVEsRUFBRSxJQUFJO1lBQ2QsYUFBYSxFQUFFLGNBQWM7U0FDOUIsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPO1FBQ0wsYUFBYSxFQUFFLFVBQVU7UUFDekIsUUFBUSxFQUFFLEtBQUs7UUFDZixhQUFhLEVBQUUsY0FBYztLQUM5QixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBTWVNURU1fT1JHX0lEIH0gZnJvbSAnLi4vbWlkZGxld2FyZS9hdXRoLmpzJztcblxuLyoqIExhemlseS1jYWNoZWQgc2V0IG9mIHN1cHBvcnQgYWxpYXNlcywgcGFyc2VkIGZyb20gU1VQUE9SVF9BTElBU0VTIG9uIGZpcnN0IGFjY2Vzcy4gKi9cbmxldCBfc3VwcG9ydEFsaWFzZXM6IFNldDxzdHJpbmc+IHwgdW5kZWZpbmVkO1xuXG5mdW5jdGlvbiBnZXRTdXBwb3J0QWxpYXNlcygpOiBTZXQ8c3RyaW5nPiB7XG4gIGlmICghX3N1cHBvcnRBbGlhc2VzKSB7XG4gICAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnYuU1VQUE9SVF9BTElBU0VTIHx8ICcnO1xuICAgIF9zdXBwb3J0QWxpYXNlcyA9IG5ldyBTZXQoXG4gICAgICByYXdcbiAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgLm1hcChhbGlhcyA9PiBhbGlhcy50cmltKCkudG9Mb3dlckNhc2UoKSlcbiAgICAgICAgLmZpbHRlcihhbGlhcyA9PiBhbGlhcy5sZW5ndGggPiAwKSxcbiAgICApO1xuICB9XG4gIHJldHVybiBfc3VwcG9ydEFsaWFzZXM7XG59XG5cbi8qKlxuICogQ2xlYXIgdGhlIG1lbW9pemVkIGFsaWFzIHNldCBzbyB0aGUgbmV4dCBhY2Nlc3MgcmUtcmVhZHMgYFNVUFBPUlRfQUxJQVNFU2AuXG4gKiBUaGUgY2FjaGUgaXMgcHJvY2Vzcy1saWZldGltZSBieSBkZXNpZ24gKGVudiBpcyBmaXhlZCBwZXIgcHJvY2Vzcyk7IHRoaXMgaG9va1xuICogZXhpc3RzIHNvIHRlc3RzIGNhbiB2YXJ5IHRoZSBlbnYgYmV0d2VlbiBjYXNlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0U3VwcG9ydEFsaWFzZXNDYWNoZSgpOiB2b2lkIHtcbiAgX3N1cHBvcnRBbGlhc2VzID0gdW5kZWZpbmVkO1xufVxuXG4vKiogV2VsbC1rbm93biBmYWxsYmFjayBzdXBwb3J0IGFsaWFzIHVzZWQgd2hlbiBTVVBQT1JUX0FMSUFTRVMgaXMgdW5jb25maWd1cmVkLiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfU1VQUE9SVF9BTElBUyA9ICdzdXBwb3J0QHBpcGVsaW5lLWJ1aWxkZXInO1xuXG4vKipcbiAqIFRoZSBQUklNQVJZIChmaXJzdC1jb25maWd1cmVkKSBzdXBwb3J0IGFsaWFzIOKAlCBmb3IgZGlzcGxheSAvIHByZWZpbGwgaW4gVUlzXG4gKiAoZS5nLiB0aGUgY29tcG9zZSBcIlRvXCIgZmllbGQpLCBzbyB0aGUgc2hvd24gdmFsdWUgaXMgZHJpdmVuIGJ5IFNVUFBPUlRfQUxJQVNFU1xuICogcmF0aGVyIHRoYW4gaGFyZGNvZGVkLiBGYWxscyBiYWNrIHRvIHtAbGluayBERUZBVUxUX1NVUFBPUlRfQUxJQVN9IHdoZW4gdGhlIGVudlxuICogaXMgdW5zZXQuIChBbGwgY29uZmlndXJlZCBhbGlhc2VzIHN0aWxsIHJlc29sdmUgdmlhIHtAbGluayByZXNvbHZlUmVjaXBpZW50QWxpYXN9LilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFByaW1hcnlTdXBwb3J0QWxpYXMoKTogc3RyaW5nIHtcbiAgZm9yIChjb25zdCBhbGlhcyBvZiBnZXRTdXBwb3J0QWxpYXNlcygpKSByZXR1cm4gYWxpYXM7XG4gIHJldHVybiBERUZBVUxUX1NVUFBPUlRfQUxJQVM7XG59XG5cbi8qKlxuICogQUxMIGNvbmZpZ3VyZWQgc3VwcG9ydCBhbGlhc2VzIChvcmRlciBwcmVzZXJ2ZWQpLCBmb3IgVUlzIHRoYXQgc3VyZmFjZSBldmVyeVxuICogc3VwcG9ydCBpbmJveCBhcyBhIGRpc3RpbmN0IHJlY2lwaWVudCBzdWdnZXN0aW9uLiBGYWxscyBiYWNrIHRvIGEgc2luZ2xlXG4gKiB7QGxpbmsgREVGQVVMVF9TVVBQT1JUX0FMSUFTfSB3aGVuIFNVUFBPUlRfQUxJQVNFUyBpcyB1bnNldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFsbFN1cHBvcnRBbGlhc2VzKCk6IHN0cmluZ1tdIHtcbiAgY29uc3QgYWxsID0gWy4uLmdldFN1cHBvcnRBbGlhc2VzKCldO1xuICByZXR1cm4gYWxsLmxlbmd0aCA+IDAgPyBhbGwgOiBbREVGQVVMVF9TVVBQT1JUX0FMSUFTXTtcbn1cblxuLyoqIFJlc3VsdCBvZiBhbGlhcyByZXNvbHV0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBbGlhc1Jlc29sdXRpb24ge1xuICAvKiogVGhlIHJlc29sdmVkIG9yZ2FuaXphdGlvbiBJRCAoZS5nLiwgJ3N5c3RlbScpLiAqL1xuICByZXNvbHZlZE9yZ0lkOiBzdHJpbmc7XG4gIC8qKiBXaGV0aGVyIHRoZSBpbnB1dCB3YXMgYW4gYWxpYXMgdGhhdCBnb3QgcmVzb2x2ZWQuICovXG4gIHdhc0FsaWFzOiBib29sZWFuO1xuICAvKiogVGhlIG9yaWdpbmFsIGlucHV0IHZhbHVlLCB1c2VmdWwgZm9yIGF1ZGl0IGxvZ2dpbmcuICovXG4gIG9yaWdpbmFsVmFsdWU6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXNvbHZlIGFuIGVtYWlsLWxpa2UgYWxpYXMgdG8gYW4gYWN0dWFsIG9yZ2FuaXphdGlvbiBJRC5cbiAqXG4gKiBJZiB0aGUgaW5wdXQgbWF0Y2hlcyBhIGNvbmZpZ3VyZWQgc3VwcG9ydCBhbGlhcywgaXQgcmVzb2x2ZXMgdG8gdGhlIHN5c3RlbVxuICogb3JnIElELiBPdGhlcndpc2UgdGhlIGlucHV0IGlzIHJldHVybmVkIGFzLWlzIChsb3dlcmNhc2VkKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVSZWNpcGllbnRBbGlhcyhyZWNpcGllbnRPcmdJZDogc3RyaW5nKTogQWxpYXNSZXNvbHV0aW9uIHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IHJlY2lwaWVudE9yZ0lkLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBhbGlhc2VzID0gZ2V0U3VwcG9ydEFsaWFzZXMoKTtcblxuICBpZiAoYWxpYXNlcy5oYXMobm9ybWFsaXplZCkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVzb2x2ZWRPcmdJZDogU1lTVEVNX09SR19JRCxcbiAgICAgIHdhc0FsaWFzOiB0cnVlLFxuICAgICAgb3JpZ2luYWxWYWx1ZTogcmVjaXBpZW50T3JnSWQsXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcmVzb2x2ZWRPcmdJZDogbm9ybWFsaXplZCxcbiAgICB3YXNBbGlhczogZmFsc2UsXG4gICAgb3JpZ2luYWxWYWx1ZTogcmVjaXBpZW50T3JnSWQsXG4gIH07XG59XG5cbiJdfQ==
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type winston from 'winston';
|
|
2
|
+
import type { AuditEvent } from '../types/audit-events.js';
|
|
3
|
+
/**
|
|
4
|
+
* Emit a cross-service audit event as a structured log line.
|
|
5
|
+
*
|
|
6
|
+
* Best-effort: if the underlying logger transport fails, the caller's
|
|
7
|
+
* mutation still succeeds — we never let audit-write failure roll back
|
|
8
|
+
* the user-visible operation. The line is tagged `eventCategory: 'audit'`
|
|
9
|
+
* so downstream log aggregators (Loki, CloudWatch) can route audit
|
|
10
|
+
* events into a separate index.
|
|
11
|
+
*
|
|
12
|
+
* For platform's own audit events (user.login, org.create, …), use
|
|
13
|
+
* platform's `helpers/audit.ts` instead — those persist to MongoDB.
|
|
14
|
+
*/
|
|
15
|
+
export declare function emitAudit(logger: winston.Logger, audit: AuditEvent): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { scrubAwsIdentifiers } from './aws-scrub.js';
|
|
4
|
+
/**
|
|
5
|
+
* Emit a cross-service audit event as a structured log line.
|
|
6
|
+
*
|
|
7
|
+
* Best-effort: if the underlying logger transport fails, the caller's
|
|
8
|
+
* mutation still succeeds — we never let audit-write failure roll back
|
|
9
|
+
* the user-visible operation. The line is tagged `eventCategory: 'audit'`
|
|
10
|
+
* so downstream log aggregators (Loki, CloudWatch) can route audit
|
|
11
|
+
* events into a separate index.
|
|
12
|
+
*
|
|
13
|
+
* For platform's own audit events (user.login, org.create, …), use
|
|
14
|
+
* platform's `helpers/audit.ts` instead — those persist to MongoDB.
|
|
15
|
+
*/
|
|
16
|
+
export function emitAudit(logger, audit) {
|
|
17
|
+
try {
|
|
18
|
+
// Scrub any AWS account-id-shaped values (e.g. an ARN in `details`) before the
|
|
19
|
+
// event lands in the durable log store — the logger's secret-key redaction
|
|
20
|
+
// doesn't cover account ids, and this is exactly the persistence boundary the
|
|
21
|
+
// "never persist an AWS account id" rule targets.
|
|
22
|
+
logger.info('audit', scrubAwsIdentifiers({ eventCategory: 'audit', ...audit }));
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
// The winston logger normally never throws synchronously, but if a
|
|
26
|
+
// transport explodes during a route call, we don't want the mutation
|
|
27
|
+
// to fail because the audit write didn't land.
|
|
28
|
+
try {
|
|
29
|
+
logger.warn('Failed to emit audit event', {
|
|
30
|
+
event: audit.event,
|
|
31
|
+
error: err instanceof Error ? err.message : String(err),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Logger itself is unrecoverable — give up silently.
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvYXVkaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUd0QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUdyRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQ3ZCLE1BQXNCLEVBQ3RCLEtBQWlCO0lBRWpCLElBQUksQ0FBQztRQUNILCtFQUErRTtRQUMvRSwyRUFBMkU7UUFDM0UsOEVBQThFO1FBQzlFLGtEQUFrRDtRQUNsRCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxtQkFBbUIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEYsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixtRUFBbUU7UUFDbkUscUVBQXFFO1FBQ3JFLCtDQUErQztRQUMvQyxJQUFJLENBQUM7WUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixFQUFFO2dCQUN4QyxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7Z0JBQ2xCLEtBQUssRUFBRSxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDO2FBQ3hELENBQUMsQ0FBQztRQUNMLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxxREFBcUQ7UUFDdkQsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB0eXBlIHdpbnN0b24gZnJvbSAnd2luc3Rvbic7XG5pbXBvcnQgeyBzY3J1YkF3c0lkZW50aWZpZXJzIH0gZnJvbSAnLi9hd3Mtc2NydWIuanMnO1xuaW1wb3J0IHR5cGUgeyBBdWRpdEV2ZW50IH0gZnJvbSAnLi4vdHlwZXMvYXVkaXQtZXZlbnRzLmpzJztcblxuLyoqXG4gKiBFbWl0IGEgY3Jvc3Mtc2VydmljZSBhdWRpdCBldmVudCBhcyBhIHN0cnVjdHVyZWQgbG9nIGxpbmUuXG4gKlxuICogQmVzdC1lZmZvcnQ6IGlmIHRoZSB1bmRlcmx5aW5nIGxvZ2dlciB0cmFuc3BvcnQgZmFpbHMsIHRoZSBjYWxsZXInc1xuICogbXV0YXRpb24gc3RpbGwgc3VjY2VlZHMg4oCUIHdlIG5ldmVyIGxldCBhdWRpdC13cml0ZSBmYWlsdXJlIHJvbGwgYmFja1xuICogdGhlIHVzZXItdmlzaWJsZSBvcGVyYXRpb24uIFRoZSBsaW5lIGlzIHRhZ2dlZCBgZXZlbnRDYXRlZ29yeTogJ2F1ZGl0J2BcbiAqIHNvIGRvd25zdHJlYW0gbG9nIGFnZ3JlZ2F0b3JzIChMb2tpLCBDbG91ZFdhdGNoKSBjYW4gcm91dGUgYXVkaXRcbiAqIGV2ZW50cyBpbnRvIGEgc2VwYXJhdGUgaW5kZXguXG4gKlxuICogRm9yIHBsYXRmb3JtJ3Mgb3duIGF1ZGl0IGV2ZW50cyAodXNlci5sb2dpbiwgb3JnLmNyZWF0ZSwg4oCmKSwgdXNlXG4gKiBwbGF0Zm9ybSdzIGBoZWxwZXJzL2F1ZGl0LnRzYCBpbnN0ZWFkIOKAlCB0aG9zZSBwZXJzaXN0IHRvIE1vbmdvREIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbWl0QXVkaXQoXG4gIGxvZ2dlcjogd2luc3Rvbi5Mb2dnZXIsXG4gIGF1ZGl0OiBBdWRpdEV2ZW50LFxuKTogdm9pZCB7XG4gIHRyeSB7XG4gICAgLy8gU2NydWIgYW55IEFXUyBhY2NvdW50LWlkLXNoYXBlZCB2YWx1ZXMgKGUuZy4gYW4gQVJOIGluIGBkZXRhaWxzYCkgYmVmb3JlIHRoZVxuICAgIC8vIGV2ZW50IGxhbmRzIGluIHRoZSBkdXJhYmxlIGxvZyBzdG9yZSDigJQgdGhlIGxvZ2dlcidzIHNlY3JldC1rZXkgcmVkYWN0aW9uXG4gICAgLy8gZG9lc24ndCBjb3ZlciBhY2NvdW50IGlkcywgYW5kIHRoaXMgaXMgZXhhY3RseSB0aGUgcGVyc2lzdGVuY2UgYm91bmRhcnkgdGhlXG4gICAgLy8gXCJuZXZlciBwZXJzaXN0IGFuIEFXUyBhY2NvdW50IGlkXCIgcnVsZSB0YXJnZXRzLlxuICAgIGxvZ2dlci5pbmZvKCdhdWRpdCcsIHNjcnViQXdzSWRlbnRpZmllcnMoeyBldmVudENhdGVnb3J5OiAnYXVkaXQnLCAuLi5hdWRpdCB9KSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIC8vIFRoZSB3aW5zdG9uIGxvZ2dlciBub3JtYWxseSBuZXZlciB0aHJvd3Mgc3luY2hyb25vdXNseSwgYnV0IGlmIGFcbiAgICAvLyB0cmFuc3BvcnQgZXhwbG9kZXMgZHVyaW5nIGEgcm91dGUgY2FsbCwgd2UgZG9uJ3Qgd2FudCB0aGUgbXV0YXRpb25cbiAgICAvLyB0byBmYWlsIGJlY2F1c2UgdGhlIGF1ZGl0IHdyaXRlIGRpZG4ndCBsYW5kLlxuICAgIHRyeSB7XG4gICAgICBsb2dnZXIud2FybignRmFpbGVkIHRvIGVtaXQgYXVkaXQgZXZlbnQnLCB7XG4gICAgICAgIGV2ZW50OiBhdWRpdC5ldmVudCxcbiAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gTG9nZ2VyIGl0c2VsZiBpcyB1bnJlY292ZXJhYmxlIOKAlCBnaXZlIHVwIHNpbGVudGx5LlxuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Redact every AWS-account-id-shaped token (incl. the account field of any ARN) from a string. */
|
|
2
|
+
export declare function scrubAwsIdentifiersFromString(input: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Deep-scrub a value (string / array / plain object) of AWS account identifiers,
|
|
5
|
+
* returning a scrubbed copy — the input is never mutated. String values have
|
|
6
|
+
* account-id tokens redacted; any key matching {@link ACCOUNT_KEY_RE} with a
|
|
7
|
+
* string/number value is redacted wholesale. Non-string primitives pass through
|
|
8
|
+
* unchanged (a bare number is only redacted when it sits under an account-named
|
|
9
|
+
* key, to avoid clobbering legitimate numeric fields).
|
|
10
|
+
*/
|
|
11
|
+
export declare function scrubAwsIdentifiers<T>(value: T): T;
|