@pipeline-builder/pipeline-core 4.1.14 → 4.1.16

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 (54) hide show
  1. package/lib/cdk.d.ts +1 -0
  2. package/lib/cdk.js +2 -1
  3. package/lib/config/app-config.d.ts +5 -8
  4. package/lib/config/app-config.js +36 -38
  5. package/lib/config/config-types.d.ts +9 -112
  6. package/lib/config/config-types.js +1 -1
  7. package/lib/config/handler-constants.d.ts +12 -3
  8. package/lib/config/handler-constants.js +9 -26
  9. package/lib/config/infrastructure-config.js +44 -43
  10. package/lib/config/server-config.d.ts +1 -1
  11. package/lib/config/server-config.js +33 -32
  12. package/lib/config/service-client.d.ts +3 -7
  13. package/lib/config/service-client.js +5 -11
  14. package/lib/core/artifact-manager.d.ts +0 -17
  15. package/lib/core/artifact-manager.js +1 -17
  16. package/lib/core/metadata-helpers.d.ts +16 -0
  17. package/lib/core/metadata-helpers.js +41 -1
  18. package/lib/core/pipeline-helpers.js +23 -58
  19. package/lib/core/plugin-contract.d.ts +126 -0
  20. package/lib/core/plugin-contract.js +217 -0
  21. package/lib/core/plugin-lookup-envelope.d.ts +14 -0
  22. package/lib/core/plugin-lookup-envelope.js +29 -0
  23. package/lib/core/step-manifest.d.ts +50 -0
  24. package/lib/core/step-manifest.js +47 -0
  25. package/lib/handlers/platform-credential.d.ts +47 -0
  26. package/lib/handlers/platform-credential.js +87 -0
  27. package/lib/handlers/plugin-lookup-handler.d.ts +1 -1
  28. package/lib/handlers/plugin-lookup-handler.js +48 -42
  29. package/lib/index.d.ts +8 -8
  30. package/lib/index.js +10 -9
  31. package/lib/pipeline/pipeline-builder.d.ts +7 -0
  32. package/lib/pipeline/pipeline-builder.js +25 -9
  33. package/lib/pipeline/pipeline-configuration.js +6 -5
  34. package/lib/pipeline/plugin-lookup.d.ts +0 -1
  35. package/lib/pipeline/plugin-lookup.js +55 -23
  36. package/lib/pipeline/plugin-spec.d.ts +41 -0
  37. package/lib/pipeline/plugin-spec.js +1 -1
  38. package/lib/pipeline/stage-builder.d.ts +11 -0
  39. package/lib/pipeline/stage-builder.js +31 -12
  40. package/lib/pipeline/step-manifest-recorder.d.ts +22 -0
  41. package/lib/pipeline/step-manifest-recorder.js +57 -0
  42. package/lib/pipeline/step-types.d.ts +16 -4
  43. package/lib/pipeline/step-types.js +1 -1
  44. package/lib/template/index.d.ts +4 -4
  45. package/lib/template/index.js +5 -5
  46. package/lib/template/plugin-resolver.js +5 -5
  47. package/lib/template/tokenizer.d.ts +4 -0
  48. package/lib/template/tokenizer.js +11 -7
  49. package/lib/testing/exports.json +72 -0
  50. package/package.json +36 -8
  51. package/lib/config/billing-config.d.ts +0 -27
  52. package/lib/config/billing-config.js +0 -534
  53. package/lib/config/entitlements.d.ts +0 -23
  54. package/lib/config/entitlements.js +0 -46
@@ -0,0 +1,126 @@
1
+ import type { MetaDataType } from './pipeline-types.js';
2
+ /** Declared coercion type of a contract key. */
3
+ export type ContractValueType = 'string' | 'number' | 'bool' | 'json';
4
+ /** The contract fields of a plugin record (as `plugins` stores them). */
5
+ export interface PluginContract {
6
+ readonly requiredMetadata?: readonly string[] | null;
7
+ readonly requiredVars?: readonly string[] | null;
8
+ readonly metadataTypes?: Readonly<Record<string, ContractValueType>> | null;
9
+ readonly varsTypes?: Readonly<Record<string, ContractValueType>> | null;
10
+ }
11
+ /** What `{{ pipeline.metadata.* }}` and `{{ pipeline.vars.* }}` resolve against. */
12
+ export interface ContractScope {
13
+ readonly metadata: Readonly<Record<string, unknown>>;
14
+ readonly vars: Readonly<Record<string, unknown>>;
15
+ }
16
+ /** One unmet contract key. */
17
+ export interface ContractIssue {
18
+ readonly kind: 'metadata' | 'vars';
19
+ readonly key: string;
20
+ readonly problem: 'missing' | 'type';
21
+ /** The declared type, for a `type` problem. */
22
+ readonly expected?: ContractValueType;
23
+ readonly message: string;
24
+ }
25
+ /** The pipeline-props fields the contract scope is built from (BuilderProps subset). */
26
+ export interface ContractScopeProps {
27
+ readonly global?: unknown;
28
+ readonly defaults?: unknown;
29
+ readonly synth?: unknown;
30
+ readonly vars?: unknown;
31
+ }
32
+ /**
33
+ * `pipeline.metadata` as synth builds it: `global` ← `defaults.metadata` ←
34
+ * `synth.metadata` (last wins). The single definition — `PipelineConfiguration`
35
+ * uses it too, so the API check and the synth scope cannot drift.
36
+ */
37
+ export declare function pipelineScopeMetadata(props: ContractScopeProps): MetaDataType;
38
+ /** The contract scope of a pipeline's props (see {@link pipelineScopeMetadata}). */
39
+ export declare function pipelineContractScope(props: ContractScopeProps): ContractScope;
40
+ /**
41
+ * The contract scope inside a synth template scope (`{ pipeline: { metadata,
42
+ * vars, … } }`, see `PipelineConfiguration.getPipelineScope`).
43
+ */
44
+ export declare function contractScopeFromTemplateScope(templateScope: Readonly<Record<string, unknown>>): ContractScope;
45
+ /**
46
+ * Does `value` satisfy the declared `type` once interpolated? Mirrors the
47
+ * evaluator's `resolveOne` (objects never interpolate) and `applyCoercion`.
48
+ */
49
+ export declare function isContractValueOfType(value: unknown, type: ContractValueType): boolean;
50
+ /**
51
+ * Check one plugin's contract against the pipeline's scope. Returns every
52
+ * issue (missing keys first, then ill-typed ones, metadata before vars);
53
+ * empty when the contract is met. Declared types are checked for every
54
+ * SUPPLIED key, required or not (an optional key with a `| default:` is still
55
+ * coerced when it is supplied).
56
+ */
57
+ export declare function checkPluginContract(contract: PluginContract, scope: ContractScope): ContractIssue[];
58
+ /**
59
+ * Synth-time guard: throw when `plugin` (resolved for `step`) has unmet
60
+ * contract keys. The API refuses such a pipeline at create/update; this
61
+ * catches one that reached synth another way.
62
+ */
63
+ export declare function assertPluginContract(plugin: PluginContract & {
64
+ readonly name: string;
65
+ readonly version?: string;
66
+ }, scope: ContractScope, step: string): void;
67
+ /** A plugin reference in pipeline props, with where it sits. */
68
+ export interface PluginStepRef {
69
+ /** JSON path of the step: `synth` or `stages[i].steps[j]`. */
70
+ readonly path: string;
71
+ /** Human label: `synth` or `<stageName>/<alias ?? name>`. */
72
+ readonly label: string;
73
+ readonly name: string;
74
+ /** Publisher handle of an installed listing. */
75
+ readonly publisher?: string;
76
+ readonly alias?: string;
77
+ readonly filter?: Readonly<Record<string, unknown>>;
78
+ }
79
+ /**
80
+ * Every plugin reference in a pipeline's props: `synth.plugin`, then each
81
+ * `stages[].steps[].plugin` in order. One entry per STEP (not de-duplicated) —
82
+ * the contract result is reported per step.
83
+ */
84
+ export declare function collectPluginSteps(props: unknown): PluginStepRef[];
85
+ /**
86
+ * The lookup filter synth sends for a reference (pipeline-manager
87
+ * `resolvePluginsForProps`, the deploy-time custom resource, the pipeline
88
+ * service's contract check): the ref's name — and its `publisher`, which
89
+ * routes the lookup to that publisher's installed listing — overlaid by
90
+ * an explicit `filter` (whose `name` wins), else the default active+default
91
+ * version.
92
+ */
93
+ export declare function pluginLookupFilter(ref: Pick<PluginStepRef, 'name' | 'filter' | 'publisher'>): Record<string, unknown>;
94
+ /**
95
+ * The plugin-alias SEGMENT of an artifact key — and the resolver's cache key:
96
+ * the explicit alias, or `${name}-alias` when there is none
97
+ * (`${publisher}-${name}-alias` for a qualified reference). THE rule — the frontend's artifact picker
98
+ * (`frontend/src/lib/artifact-keys.ts`), the CLI's pre-resolver and
99
+ * `PluginLookup.normalize` all build keys this way.
100
+ *
101
+ * The places that REGISTER keys must use it too: a stage step registering the
102
+ * bare name (`nodejs-build`) or a synth step suffixing an explicit alias
103
+ * (`my-synth-alias`) would fail any UI-picked input artifact with "No artifact
104
+ * registered", because the key it asks for is never the key that was stored.
105
+ */
106
+ export declare function pluginArtifactAlias(plugin: PluginRefIdentity): string;
107
+ /** The fields of a plugin REFERENCE that identify it. */
108
+ export interface PluginRefIdentity {
109
+ readonly name: string;
110
+ readonly alias?: string;
111
+ /** Publisher handle of an installed listing; absent for an unqualified reference. */
112
+ readonly publisher?: string;
113
+ }
114
+ /**
115
+ * A publisher handle as it may appear in a construct id or a key: only
116
+ * `[A-Za-z0-9_-]` (handles already are; this is the guarantee).
117
+ */
118
+ export declare function sanitizePublisher(publisher: string): string;
119
+ /**
120
+ * The construct-id segment of a plugin step: the explicit alias, else
121
+ * `<publisher>-<name>` for a qualified reference, else the bare name — so a
122
+ * step using `acme`'s `lint` and one using the org's own `lint` never collide,
123
+ * while an unqualified step keeps the id it always had (renaming it would make
124
+ * CloudFormation replace its CodeBuild project).
125
+ */
126
+ export declare function pluginStepIdAlias(plugin: PluginRefIdentity): string;
@@ -0,0 +1,217 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Plugin contract enforcement. A plugin spec declares
5
+ * the `{{ pipeline.metadata.X }}` / `{{ pipeline.vars.X }}` keys a pipeline
6
+ * must supply (`requiredMetadata` / `requiredVars`) and the coercion type of
7
+ * each (`metadataTypes` / `varsTypes`). The upload validates the spec against
8
+ * its own templates; this module checks a PIPELINE against the contracts of
9
+ * the plugins it references.
10
+ *
11
+ * CDK-free: shared by the pipeline service (create / update → 400 listing
12
+ * every problem per step) and the synth (fail fast for a pipeline that never
13
+ * went through the API, e.g. a CLI-authored props file).
14
+ *
15
+ * The checks mirror the template evaluator (`template/evaluator.ts`) exactly,
16
+ * so "passes here" means "resolves at synth":
17
+ * - a key is MISSING when absent, null or the empty string (the evaluator
18
+ * falls to `| default:` or fails for all three);
19
+ * - an object/array value never interpolates;
20
+ * - `number` / `bool` / `json` accept what the `| number` / `| bool` /
21
+ * `| json` filters accept after stringification.
22
+ */
23
+ import { merge } from './metadata-helpers.js';
24
+ function asRecord(v) {
25
+ return v && typeof v === 'object' && !Array.isArray(v) ? v : {};
26
+ }
27
+ /**
28
+ * `pipeline.metadata` as synth builds it: `global` ← `defaults.metadata` ←
29
+ * `synth.metadata` (last wins). The single definition — `PipelineConfiguration`
30
+ * uses it too, so the API check and the synth scope cannot drift.
31
+ */
32
+ export function pipelineScopeMetadata(props) {
33
+ return merge(asRecord(props.global), asRecord(asRecord(props.defaults).metadata), asRecord(asRecord(props.synth).metadata));
34
+ }
35
+ /** The contract scope of a pipeline's props (see {@link pipelineScopeMetadata}). */
36
+ export function pipelineContractScope(props) {
37
+ return { metadata: pipelineScopeMetadata(props), vars: asRecord(props.vars) };
38
+ }
39
+ /**
40
+ * The contract scope inside a synth template scope (`{ pipeline: { metadata,
41
+ * vars, … } }`, see `PipelineConfiguration.getPipelineScope`).
42
+ */
43
+ export function contractScopeFromTemplateScope(templateScope) {
44
+ const pipeline = asRecord(templateScope.pipeline);
45
+ return { metadata: asRecord(pipeline.metadata), vars: asRecord(pipeline.vars) };
46
+ }
47
+ /** Would the evaluator treat `value` as absent (missing / null / empty string)? */
48
+ function isMissing(value) {
49
+ return value === undefined || value === null || value === '';
50
+ }
51
+ /**
52
+ * Does `value` satisfy the declared `type` once interpolated? Mirrors the
53
+ * evaluator's `resolveOne` (objects never interpolate) and `applyCoercion`.
54
+ */
55
+ export function isContractValueOfType(value, type) {
56
+ if (typeof value === 'object' && value !== null)
57
+ return false;
58
+ const raw = String(value);
59
+ switch (type) {
60
+ case 'string':
61
+ return true;
62
+ case 'number':
63
+ return Number.isFinite(Number(raw));
64
+ case 'bool':
65
+ return ['true', '1', 'yes', 'false', '0', 'no', ''].includes(raw.trim().toLowerCase());
66
+ case 'json':
67
+ try {
68
+ JSON.parse(raw);
69
+ return true;
70
+ }
71
+ catch {
72
+ return false;
73
+ }
74
+ }
75
+ }
76
+ /** A value still carrying `{{ … }}` is resolved later (pipeline pass 1), so its type can't be judged yet. */
77
+ function isUnresolvedTemplate(value) {
78
+ return typeof value === 'string' && value.includes('{{');
79
+ }
80
+ function checkKind(kind, required, types, supplied) {
81
+ const issues = [];
82
+ const where = kind === 'metadata' ? 'metadata (global / defaults.metadata / synth.metadata)' : 'vars';
83
+ for (const key of new Set(required ?? [])) {
84
+ if (isMissing(supplied[key])) {
85
+ issues.push({ kind, key, problem: 'missing', message: `pipeline ${where} must supply '${key}'` });
86
+ }
87
+ }
88
+ for (const [key, expected] of Object.entries(types ?? {})) {
89
+ const value = supplied[key];
90
+ if (isMissing(value) || isUnresolvedTemplate(value))
91
+ continue;
92
+ if (!isContractValueOfType(value, expected)) {
93
+ const got = typeof value === 'object' ? (Array.isArray(value) ? 'an array' : 'an object') : JSON.stringify(value);
94
+ issues.push({ kind, key, problem: 'type', expected, message: `pipeline ${kind}.${key} must be a ${expected}, got ${got}` });
95
+ }
96
+ }
97
+ return issues;
98
+ }
99
+ /**
100
+ * Check one plugin's contract against the pipeline's scope. Returns every
101
+ * issue (missing keys first, then ill-typed ones, metadata before vars);
102
+ * empty when the contract is met. Declared types are checked for every
103
+ * SUPPLIED key, required or not (an optional key with a `| default:` is still
104
+ * coerced when it is supplied).
105
+ */
106
+ export function checkPluginContract(contract, scope) {
107
+ return [
108
+ ...checkKind('metadata', contract.requiredMetadata, contract.metadataTypes, scope.metadata),
109
+ ...checkKind('vars', contract.requiredVars, contract.varsTypes, scope.vars),
110
+ ];
111
+ }
112
+ /**
113
+ * Synth-time guard: throw when `plugin` (resolved for `step`) has unmet
114
+ * contract keys. The API refuses such a pipeline at create/update; this
115
+ * catches one that reached synth another way.
116
+ */
117
+ export function assertPluginContract(plugin, scope, step) {
118
+ const issues = checkPluginContract(plugin, scope);
119
+ if (issues.length === 0)
120
+ return;
121
+ throw new Error(`Step "${step}" uses plugin "${plugin.name}${plugin.version ? `@${plugin.version}` : ''}" whose contract is not met:\n`
122
+ + issues.map((i) => ` • ${i.message}`).join('\n'));
123
+ }
124
+ function toRef(raw, path, label) {
125
+ const r = asRecord(raw);
126
+ if (typeof r.name !== 'string' || r.name.length === 0)
127
+ return null;
128
+ const alias = typeof r.alias === 'string' ? r.alias : undefined;
129
+ const publisher = typeof r.publisher === 'string' && r.publisher.length > 0 ? r.publisher : undefined;
130
+ const filter = r.filter && typeof r.filter === 'object' ? r.filter : undefined;
131
+ return {
132
+ path,
133
+ label: label(r.name, alias, publisher),
134
+ name: r.name,
135
+ ...(publisher ? { publisher } : {}),
136
+ ...(alias ? { alias } : {}),
137
+ ...(filter ? { filter } : {}),
138
+ };
139
+ }
140
+ /**
141
+ * Every plugin reference in a pipeline's props: `synth.plugin`, then each
142
+ * `stages[].steps[].plugin` in order. One entry per STEP (not de-duplicated) —
143
+ * the contract result is reported per step.
144
+ */
145
+ export function collectPluginSteps(props) {
146
+ const p = asRecord(props);
147
+ const out = [];
148
+ const synth = toRef(asRecord(p.synth).plugin, 'synth', () => 'synth');
149
+ if (synth)
150
+ out.push(synth);
151
+ const stages = Array.isArray(p.stages) ? p.stages : [];
152
+ stages.forEach((stage, i) => {
153
+ const s = asRecord(stage);
154
+ const stageName = typeof s.stageName === 'string' ? s.stageName : `stage ${i + 1}`;
155
+ const steps = Array.isArray(s.steps) ? s.steps : [];
156
+ steps.forEach((step, j) => {
157
+ const ref = toRef(asRecord(step).plugin, `stages[${i}].steps[${j}]`, (name, alias, publisher) => `${stageName}/${alias ?? (publisher ? `${publisher}/${name}` : name)}`);
158
+ if (ref)
159
+ out.push(ref);
160
+ });
161
+ });
162
+ return out;
163
+ }
164
+ /**
165
+ * The lookup filter synth sends for a reference (pipeline-manager
166
+ * `resolvePluginsForProps`, the deploy-time custom resource, the pipeline
167
+ * service's contract check): the ref's name — and its `publisher`, which
168
+ * routes the lookup to that publisher's installed listing — overlaid by
169
+ * an explicit `filter` (whose `name` wins), else the default active+default
170
+ * version.
171
+ */
172
+ export function pluginLookupFilter(ref) {
173
+ return {
174
+ name: ref.name,
175
+ ...(ref.publisher ? { publisher: ref.publisher } : {}),
176
+ ...(ref.filter ?? { isActive: true, isDefault: true }),
177
+ };
178
+ }
179
+ // -----------------------------------------------------------------------------
180
+ // Reference identity (CDK-free: the CLI, the pipeline service and synth share it)
181
+ // -----------------------------------------------------------------------------
182
+ /**
183
+ * The plugin-alias SEGMENT of an artifact key — and the resolver's cache key:
184
+ * the explicit alias, or `${name}-alias` when there is none
185
+ * (`${publisher}-${name}-alias` for a qualified reference). THE rule — the frontend's artifact picker
186
+ * (`frontend/src/lib/artifact-keys.ts`), the CLI's pre-resolver and
187
+ * `PluginLookup.normalize` all build keys this way.
188
+ *
189
+ * The places that REGISTER keys must use it too: a stage step registering the
190
+ * bare name (`nodejs-build`) or a synth step suffixing an explicit alias
191
+ * (`my-synth-alias`) would fail any UI-picked input artifact with "No artifact
192
+ * registered", because the key it asks for is never the key that was stored.
193
+ */
194
+ export function pluginArtifactAlias(plugin) {
195
+ if (plugin.alias)
196
+ return plugin.alias;
197
+ return plugin.publisher ? `${sanitizePublisher(plugin.publisher)}-${plugin.name}-alias` : `${plugin.name}-alias`;
198
+ }
199
+ /**
200
+ * A publisher handle as it may appear in a construct id or a key: only
201
+ * `[A-Za-z0-9_-]` (handles already are; this is the guarantee).
202
+ */
203
+ export function sanitizePublisher(publisher) {
204
+ return publisher.replace(/[^A-Za-z0-9_-]/g, '-');
205
+ }
206
+ /**
207
+ * The construct-id segment of a plugin step: the explicit alias, else
208
+ * `<publisher>-<name>` for a qualified reference, else the bare name — so a
209
+ * step using `acme`'s `lint` and one using the org's own `lint` never collide,
210
+ * while an unqualified step keeps the id it always had (renaming it would make
211
+ * CloudFormation replace its CodeBuild project).
212
+ */
213
+ export function pluginStepIdAlias(plugin) {
214
+ // `??`, not `||`: an explicit (even empty) alias keeps the id it always had.
215
+ return plugin.alias ?? (plugin.publisher ? `${sanitizePublisher(plugin.publisher)}-${plugin.name}` : plugin.name);
216
+ }
217
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWNvbnRyYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvcmUvcGx1Z2luLWNvbnRyYWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFzQzlDLFNBQVMsUUFBUSxDQUFDLENBQVU7SUFDMUIsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBNEIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQzdGLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQixDQUFDLEtBQXlCO0lBQzdELE9BQU8sS0FBSyxDQUNWLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFpQixFQUN0QyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQWlCLEVBQzNELFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FBaUIsQ0FDekQsQ0FBQztBQUNKLENBQUM7QUFFRCxvRkFBb0Y7QUFDcEYsTUFBTSxVQUFVLHFCQUFxQixDQUFDLEtBQXlCO0lBQzdELE9BQU8sRUFBRSxRQUFRLEVBQUUscUJBQXFCLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztBQUNoRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLDhCQUE4QixDQUFDLGFBQWdEO0lBQzdGLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEQs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QUFDO0lBQ3RDLE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLFFBQVEsQ0FBQztBQUNuSCxDQUFDO0FBVUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLFNBQWlCO0lBQ2pELE9BQU8sU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLE1BQXlCO0lBQ3pELDZFQUE2RTtJQUM3RSxPQUFPLE1BQU0sQ0FBQyxLQUFLLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUNwSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogUGx1Z2luIGNvbnRyYWN0IGVuZm9yY2VtZW50LiBBIHBsdWdpbiBzcGVjIGRlY2xhcmVzXG4gKiB0aGUgYHt7IHBpcGVsaW5lLm1ldGFkYXRhLlggfX1gIC8gYHt7IHBpcGVsaW5lLnZhcnMuWCB9fWAga2V5cyBhIHBpcGVsaW5lXG4gKiBtdXN0IHN1cHBseSAoYHJlcXVpcmVkTWV0YWRhdGFgIC8gYHJlcXVpcmVkVmFyc2ApIGFuZCB0aGUgY29lcmNpb24gdHlwZSBvZlxuICogZWFjaCAoYG1ldGFkYXRhVHlwZXNgIC8gYHZhcnNUeXBlc2ApLiBUaGUgdXBsb2FkIHZhbGlkYXRlcyB0aGUgc3BlYyBhZ2FpbnN0XG4gKiBpdHMgb3duIHRlbXBsYXRlczsgdGhpcyBtb2R1bGUgY2hlY2tzIGEgUElQRUxJTkUgYWdhaW5zdCB0aGUgY29udHJhY3RzIG9mXG4gKiB0aGUgcGx1Z2lucyBpdCByZWZlcmVuY2VzLlxuICpcbiAqIENESy1mcmVlOiBzaGFyZWQgYnkgdGhlIHBpcGVsaW5lIHNlcnZpY2UgKGNyZWF0ZSAvIHVwZGF0ZSDihpIgNDAwIGxpc3RpbmdcbiAqIGV2ZXJ5IHByb2JsZW0gcGVyIHN0ZXApIGFuZCB0aGUgc3ludGggKGZhaWwgZmFzdCBmb3IgYSBwaXBlbGluZSB0aGF0IG5ldmVyXG4gKiB3ZW50IHRocm91Z2ggdGhlIEFQSSwgZS5nLiBhIENMSS1hdXRob3JlZCBwcm9wcyBmaWxlKS5cbiAqXG4gKiBUaGUgY2hlY2tzIG1pcnJvciB0aGUgdGVtcGxhdGUgZXZhbHVhdG9yIChgdGVtcGxhdGUvZXZhbHVhdG9yLnRzYCkgZXhhY3RseSxcbiAqIHNvIFwicGFzc2VzIGhlcmVcIiBtZWFucyBcInJlc29sdmVzIGF0IHN5bnRoXCI6XG4gKiAgIC0gYSBrZXkgaXMgTUlTU0lORyB3aGVuIGFic2VudCwgbnVsbCBvciB0aGUgZW1wdHkgc3RyaW5nICh0aGUgZXZhbHVhdG9yXG4gKiAgICAgZmFsbHMgdG8gYHwgZGVmYXVsdDpgIG9yIGZhaWxzIGZvciBhbGwgdGhyZWUpO1xuICogICAtIGFuIG9iamVjdC9hcnJheSB2YWx1ZSBuZXZlciBpbnRlcnBvbGF0ZXM7XG4gKiAgIC0gYG51bWJlcmAgLyBgYm9vbGAgLyBganNvbmAgYWNjZXB0IHdoYXQgdGhlIGB8IG51bWJlcmAgLyBgfCBib29sYCAvXG4gKiAgICAgYHwganNvbmAgZmlsdGVycyBhY2NlcHQgYWZ0ZXIgc3RyaW5naWZpY2F0aW9uLlxuICovXG5cbmltcG9ydCB7IG1lcmdlIH0gZnJvbSAnLi9tZXRhZGF0YS1oZWxwZXJzLmpzJztcbmltcG9ydCB0eXBlIHsgTWV0YURhdGFUeXBlIH0gZnJvbSAnLi9waXBlbGluZS10eXBlcy5qcyc7XG5cbi8qKiBEZWNsYXJlZCBjb2VyY2lvbiB0eXBlIG9mIGEgY29udHJhY3Qga2V5LiAqL1xuZXhwb3J0IHR5cGUgQ29udHJhY3RWYWx1ZVR5cGUgPSAnc3RyaW5nJyB8ICdudW1iZXInIHwgJ2Jvb2wnIHwgJ2pzb24nO1xuXG4vKiogVGhlIGNvbnRyYWN0IGZpZWxkcyBvZiBhIHBsdWdpbiByZWNvcmQgKGFzIGBwbHVnaW5zYCBzdG9yZXMgdGhlbSkuICovXG5leHBvcnQgaW50ZXJmYWNlIFBsdWdpbkNvbnRyYWN0IHtcbiAgcmVhZG9ubHkgcmVxdWlyZWRNZXRhZGF0YT86IHJlYWRvbmx5IHN0cmluZ1tdIHwgbnVsbDtcbiAgcmVhZG9ubHkgcmVxdWlyZWRWYXJzPzogcmVhZG9ubHkgc3RyaW5nW10gfCBudWxsO1xuICByZWFkb25seSBtZXRhZGF0YVR5cGVzPzogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgQ29udHJhY3RWYWx1ZVR5cGU+PiB8IG51bGw7XG4gIHJlYWRvbmx5IHZhcnNUeXBlcz86IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIENvbnRyYWN0VmFsdWVUeXBlPj4gfCBudWxsO1xufVxuXG4vKiogV2hhdCBge3sgcGlwZWxpbmUubWV0YWRhdGEuKiB9fWAgYW5kIGB7eyBwaXBlbGluZS52YXJzLiogfX1gIHJlc29sdmUgYWdhaW5zdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29udHJhY3RTY29wZSB7XG4gIHJlYWRvbmx5IG1ldGFkYXRhOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG4gIHJlYWRvbmx5IHZhcnM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcbn1cblxuLyoqIE9uZSB1bm1ldCBjb250cmFjdCBrZXkuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRyYWN0SXNzdWUge1xuICByZWFkb25seSBraW5kOiAnbWV0YWRhdGEnIHwgJ3ZhcnMnO1xuICByZWFkb25seSBrZXk6IHN0cmluZztcbiAgcmVhZG9ubHkgcHJvYmxlbTogJ21pc3NpbmcnIHwgJ3R5cGUnO1xuICAvKiogVGhlIGRlY2xhcmVkIHR5cGUsIGZvciBhIGB0eXBlYCBwcm9ibGVtLiAqL1xuICByZWFkb25seSBleHBlY3RlZD86IENvbnRyYWN0VmFsdWVUeXBlO1xuICByZWFkb25seSBtZXNzYWdlOiBzdHJpbmc7XG59XG5cbi8qKiBUaGUgcGlwZWxpbmUtcHJvcHMgZmllbGRzIHRoZSBjb250cmFjdCBzY29wZSBpcyBidWlsdCBmcm9tIChCdWlsZGVyUHJvcHMgc3Vic2V0KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29udHJhY3RTY29wZVByb3BzIHtcbiAgcmVhZG9ubHkgZ2xvYmFsPzogdW5rbm93bjtcbiAgcmVhZG9ubHkgZGVmYXVsdHM/OiB1bmtub3duO1xuICByZWFkb25seSBzeW50aD86IHVua25vd247XG4gIHJlYWRvbmx5IHZhcnM/OiB1bmtub3duO1xufVxuXG5mdW5jdGlvbiBhc1JlY29yZCh2OiB1bmtub3duKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICByZXR1cm4gdiAmJiB0eXBlb2YgdiA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkodikgPyB2IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IDoge307XG59XG5cbi8qKlxuICogYHBpcGVsaW5lLm1ldGFkYXRhYCBhcyBzeW50aCBidWlsZHMgaXQ6IGBnbG9iYWxgIOKGkCBgZGVmYXVsdHMubWV0YWRhdGFgIOKGkFxuICogYHN5bnRoLm1ldGFkYXRhYCAobGFzdCB3aW5zKS4gVGhlIHNpbmdsZSBkZWZpbml0aW9uIOKAlCBgUGlwZWxpbmVDb25maWd1cmF0aW9uYFxuICogdXNlcyBpdCB0b28sIHNvIHRoZSBBUEkgY2hlY2sgYW5kIHRoZSBzeW50aCBzY29wZSBjYW5ub3QgZHJpZnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwaXBlbGluZVNjb3BlTWV0YWRhdGEocHJvcHM6IENvbnRyYWN0U2NvcGVQcm9wcyk6IE1ldGFEYXRhVHlwZSB7XG4gIHJldHVybiBtZXJnZShcbiAgICBhc1JlY29yZChwcm9wcy5nbG9iYWwpIGFzIE1ldGFEYXRhVHlwZSxcbiAgICBhc1JlY29yZChhc1JlY29yZChwcm9wcy5kZWZhdWx0cykubWV0YWRhdGEpIGFzIE1ldGFEYXRhVHlwZSxcbiAgICBhc1JlY29yZChhc1JlY29yZChwcm9wcy5zeW50aCkubWV0YWRhdGEpIGFzIE1ldGFEYXRhVHlwZSxcbiAgKTtcbn1cblxuLyoqIFRoZSBjb250cmFjdCBzY29wZSBvZiBhIHBpcGVsaW5lJ3MgcHJvcHMgKHNlZSB7QGxpbmsgcGlwZWxpbmVTY29wZU1ldGFkYXRhfSkuICovXG5leHBvcnQgZnVuY3Rpb24gcGlwZWxpbmVDb250cmFjdFNjb3BlKHByb3BzOiBDb250cmFjdFNjb3BlUHJvcHMpOiBDb250cmFjdFNjb3BlIHtcbiAgcmV0dXJuIHsgbWV0YWRhdGE6IHBpcGVsaW5lU2NvcGVNZXRhZGF0YShwcm9wcyksIHZhcnM6IGFzUmVjb3JkKHByb3BzLnZhcnMpIH07XG59XG5cbi8qKlxuICogVGhlIGNvbnRyYWN0IHNjb3BlIGluc2lkZSBhIHN5bnRoIHRlbXBsYXRlIHNjb3BlIChgeyBwaXBlbGluZTogeyBtZXRhZGF0YSxcbiAqIHZhcnMsIOKApiB9IH1gLCBzZWUgYFBpcGVsaW5lQ29uZmlndXJhdGlvbi5nZXRQaXBlbGluZVNjb3BlYCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb250cmFjdFNjb3BlRnJvbVRlbXBsYXRlU2NvcGUodGVtcGxhdGVTY29wZTogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KTogQ29udHJhY3RTY29wZSB7XG4gIGNvbnN0IHBpcGVsaW5lID0gYXNSZWNvcmQodGVtcGxhdGVTY29wZS5waXBlbGluZSk7XG4gIHJldHVybiB7IG1ldGFkYXRhOiBhc1JlY29yZChwaXBlbGluZS5tZXRhZGF0YSksIHZhcnM6IGFzUmVjb3JkKHBpcGVsaW5lLnZhcnMpIH07XG59XG5cbi8qKiBXb3VsZCB0aGUgZXZhbHVhdG9yIHRyZWF0IGB2YWx1ZWAgYXMgYWJzZW50IChtaXNzaW5nIC8gbnVsbCAvIGVtcHR5IHN0cmluZyk/ICovXG5mdW5jdGlvbiBpc01pc3NpbmcodmFsdWU6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09ICcnO1xufVxuXG4vKipcbiAqIERvZXMgYHZhbHVlYCBzYXRpc2Z5IHRoZSBkZWNsYXJlZCBgdHlwZWAgb25jZSBpbnRlcnBvbGF0ZWQ/IE1pcnJvcnMgdGhlXG4gKiBldmFsdWF0b3IncyBgcmVzb2x2ZU9uZWAgKG9iamVjdHMgbmV2ZXIgaW50ZXJwb2xhdGUpIGFuZCBgYXBwbHlDb2VyY2lvbmAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbnRyYWN0VmFsdWVPZlR5cGUodmFsdWU6IHVua25vd24sIHR5cGU6IENvbnRyYWN0VmFsdWVUeXBlKTogYm9vbGVhbiB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHJhdyA9IFN0cmluZyh2YWx1ZSk7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShOdW1iZXIocmF3KSk7XG4gICAgY2FzZSAnYm9vbCc6XG4gICAgICByZXR1cm4gWyd0cnVlJywgJzEnLCAneWVzJywgJ2ZhbHNlJywgJzAnLCAnbm8nLCAnJ10uaW5jbHVkZXMocmF3LnRyaW0oKS50b0xvd2VyQ2FzZSgpKTtcbiAgICBjYXNlICdqc29uJzpcbiAgICAgIHRyeSB7XG4gICAgICAgIEpTT04ucGFyc2UocmF3KTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICB9XG59XG5cbi8qKiBBIHZhbHVlIHN0aWxsIGNhcnJ5aW5nIGB7eyDigKYgfX1gIGlzIHJlc29sdmVkIGxhdGVyIChwaXBlbGluZSBwYXNzIDEpLCBzbyBpdHMgdHlwZSBjYW4ndCBiZSBqdWRnZWQgeWV0LiAqL1xuZnVuY3Rpb24gaXNVbnJlc29sdmVkVGVtcGxhdGUodmFsdWU6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUuaW5jbHVkZXMoJ3t7Jyk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrS2luZChcbiAga2luZDogJ21ldGFkYXRhJyB8ICd2YXJzJyxcbiAgcmVxdWlyZWQ6IHJlYWRvbmx5IHN0cmluZ1tdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgdHlwZXM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIENvbnRyYWN0VmFsdWVUeXBlPj4gfCBudWxsIHwgdW5kZWZpbmVkLFxuICBzdXBwbGllZDogUmVhZG9ubHk8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+LFxuKTogQ29udHJhY3RJc3N1ZVtdIHtcbiAgY29uc3QgaXNzdWVzOiBDb250cmFjdElzc3VlW10gPSBbXTtcbiAgY29uc3Qgd2hlcmUgPSBraW5kID09PSAnbWV0YWRhdGEnID8gJ21ldGFkYXRhIChnbG9iYWwgLyBkZWZhdWx0cy5tZXRhZGF0YSAvIHN5bnRoLm1ldGFkYXRhKScgOiAndmFycyc7XG4gIGZvciAoY29uc3Qga2V5IG9mIG5ldyBTZXQocmVxdWlyZWQgPz8gW10pKSB7XG4gICAgaWYgKGlzTWlzc2luZyhzdXBwbGllZFtrZXldKSkge1xuICAgICAgaXNzdWVzLnB1c2goeyBraW5kLCBrZXksIHByb2JsZW06ICdtaXNzaW5nJywgbWVzc2FnZTogYHBpcGVsaW5lICR7d2hlcmV9IG11c3Qgc3VwcGx5ICcke2tleX0nYCB9KTtcbiAgICB9XG4gIH1cbiAgZm9yIChjb25zdCBba2V5LCBleHBlY3RlZF0gb2YgT2JqZWN0LmVudHJpZXModHlwZXMgPz8ge30pKSB7XG4gICAgY29uc3QgdmFsdWUgPSBzdXBwbGllZFtrZXldO1xuICAgIGlmIChpc01pc3NpbmcodmFsdWUpIHx8IGlzVW5yZXNvbHZlZFRlbXBsYXRlKHZhbHVlKSkgY29udGludWU7XG4gICAgaWYgKCFpc0NvbnRyYWN0VmFsdWVPZlR5cGUodmFsdWUsIGV4cGVjdGVkKSkge1xuICAgICAgY29uc3QgZ290ID0gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyA/IChBcnJheS5pc0FycmF5KHZhbHVlKSA/ICdhbiBhcnJheScgOiAnYW4gb2JqZWN0JykgOiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgICBpc3N1ZXMucHVzaCh7IGtpbmQsIGtleSwgcHJvYmxlbTogJ3R5cGUnLCBleHBlY3RlZCwgbWVzc2FnZTogYHBpcGVsaW5lICR7a2luZH0uJHtrZXl9IG11c3QgYmUgYSAke2V4cGVjdGVkfSwgZ290ICR7Z290fWAgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBpc3N1ZXM7XG59XG5cbi8qKlxuICogQ2hlY2sgb25lIHBsdWdpbidzIGNvbnRyYWN0IGFnYWluc3QgdGhlIHBpcGVsaW5lJ3Mgc2NvcGUuIFJldHVybnMgZXZlcnlcbiAqIGlzc3VlIChtaXNzaW5nIGtleXMgZmlyc3QsIHRoZW4gaWxsLXR5cGVkIG9uZXMsIG1ldGFkYXRhIGJlZm9yZSB2YXJzKTtcbiAqIGVtcHR5IHdoZW4gdGhlIGNvbnRyYWN0IGlzIG1ldC4gRGVjbGFyZWQgdHlwZXMgYXJlIGNoZWNrZWQgZm9yIGV2ZXJ5XG4gKiBTVVBQTElFRCBrZXksIHJlcXVpcmVkIG9yIG5vdCAoYW4gb3B0aW9uYWwga2V5IHdpdGggYSBgfCBkZWZhdWx0OmAgaXMgc3RpbGxcbiAqIGNvZXJjZWQgd2hlbiBpdCBpcyBzdXBwbGllZCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGVja1BsdWdpbkNvbnRyYWN0KGNvbnRyYWN0OiBQbHVnaW5Db250cmFjdCwgc2NvcGU6IENvbnRyYWN0U2NvcGUpOiBDb250cmFjdElzc3VlW10ge1xuICByZXR1cm4gW1xuICAgIC4uLmNoZWNrS2luZCgnbWV0YWRhdGEnLCBjb250cmFjdC5yZXF1aXJlZE1ldGFkYXRhLCBjb250cmFjdC5tZXRhZGF0YVR5cGVzLCBzY29wZS5tZXRhZGF0YSksXG4gICAgLi4uY2hlY2tLaW5kKCd2YXJzJywgY29udHJhY3QucmVxdWlyZWRWYXJzLCBjb250cmFjdC52YXJzVHlwZXMsIHNjb3BlLnZhcnMpLFxuICBdO1xufVxuXG4vKipcbiAqIFN5bnRoLXRpbWUgZ3VhcmQ6IHRocm93IHdoZW4gYHBsdWdpbmAgKHJlc29sdmVkIGZvciBgc3RlcGApIGhhcyB1bm1ldFxuICogY29udHJhY3Qga2V5cy4gVGhlIEFQSSByZWZ1c2VzIHN1Y2ggYSBwaXBlbGluZSBhdCBjcmVhdGUvdXBkYXRlOyB0aGlzXG4gKiBjYXRjaGVzIG9uZSB0aGF0IHJlYWNoZWQgc3ludGggYW5vdGhlciB3YXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRQbHVnaW5Db250cmFjdChcbiAgcGx1Z2luOiBQbHVnaW5Db250cmFjdCAmIHsgcmVhZG9ubHkgbmFtZTogc3RyaW5nOyByZWFkb25seSB2ZXJzaW9uPzogc3RyaW5nIH0sXG4gIHNjb3BlOiBDb250cmFjdFNjb3BlLFxuICBzdGVwOiBzdHJpbmcsXG4pOiB2b2lkIHtcbiAgY29uc3QgaXNzdWVzID0gY2hlY2tQbHVnaW5Db250cmFjdChwbHVnaW4sIHNjb3BlKTtcbiAgaWYgKGlzc3Vlcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgdGhyb3cgbmV3IEVycm9yKFxuICAgIGBTdGVwIFwiJHtzdGVwfVwiIHVzZXMgcGx1Z2luIFwiJHtwbHVnaW4ubmFtZX0ke3BsdWdpbi52ZXJzaW9uID8gYEAke3BsdWdpbi52ZXJzaW9ufWAgOiAnJ31cIiB3aG9zZSBjb250cmFjdCBpcyBub3QgbWV0OlxcbmBcbiAgICArIGlzc3Vlcy5tYXAoKGkpID0+IGAgIOKAoiAke2kubWVzc2FnZX1gKS5qb2luKCdcXG4nKSxcbiAgKTtcbn1cblxuLyoqIEEgcGx1Z2luIHJlZmVyZW5jZSBpbiBwaXBlbGluZSBwcm9wcywgd2l0aCB3aGVyZSBpdCBzaXRzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5TdGVwUmVmIHtcbiAgLyoqIEpTT04gcGF0aCBvZiB0aGUgc3RlcDogYHN5bnRoYCBvciBgc3RhZ2VzW2ldLnN0ZXBzW2pdYC4gKi9cbiAgcmVhZG9ubHkgcGF0aDogc3RyaW5nO1xuICAvKiogSHVtYW4gbGFiZWw6IGBzeW50aGAgb3IgYDxzdGFnZU5hbWU+LzxhbGlhcyA/PyBuYW1lPmAuICovXG4gIHJlYWRvbmx5IGxhYmVsOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgLyoqIFB1Ymxpc2hlciBoYW5kbGUgb2YgYW4gaW5zdGFsbGVkIGxpc3RpbmcuICovXG4gIHJlYWRvbmx5IHB1Ymxpc2hlcj86IHN0cmluZztcbiAgcmVhZG9ubHkgYWxpYXM/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZpbHRlcj86IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+Pjtcbn1cblxuZnVuY3Rpb24gdG9SZWYocmF3OiB1bmtub3duLCBwYXRoOiBzdHJpbmcsIGxhYmVsOiAobmFtZTogc3RyaW5nLCBhbGlhcz86IHN0cmluZywgcHVibGlzaGVyPzogc3RyaW5nKSA9PiBzdHJpbmcpOiBQbHVnaW5TdGVwUmVmIHwgbnVsbCB7XG4gIGNvbnN0IHIgPSBhc1JlY29yZChyYXcpO1xuICBpZiAodHlwZW9mIHIubmFtZSAhPT0gJ3N0cmluZycgfHwgci5uYW1lLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IGFsaWFzID0gdHlwZW9mIHIuYWxpYXMgPT09ICdzdHJpbmcnID8gci5hbGlhcyA6IHVuZGVmaW5lZDtcbiAgY29uc3QgcHVibGlzaGVyID0gdHlwZW9mIHIucHVibGlzaGVyID09PSAnc3RyaW5nJyAmJiByLnB1Ymxpc2hlci5sZW5ndGggPiAwID8gci5wdWJsaXNoZXIgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IGZpbHRlciA9IHIuZmlsdGVyICYmIHR5cGVvZiByLmZpbHRlciA9PT0gJ29iamVjdCcgPyByLmZpbHRlciBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA6IHVuZGVmaW5lZDtcbiAgcmV0dXJuIHtcbiAgICBwYXRoLFxuICAgIGxhYmVsOiBsYWJlbChyLm5hbWUsIGFsaWFzLCBwdWJsaXNoZXIpLFxuICAgIG5hbWU6IHIubmFtZSxcbiAgICAuLi4ocHVibGlzaGVyID8geyBwdWJsaXNoZXIgfSA6IHt9KSxcbiAgICAuLi4oYWxpYXMgPyB7IGFsaWFzIH0gOiB7fSksXG4gICAgLi4uKGZpbHRlciA/IHsgZmlsdGVyIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKlxuICogRXZlcnkgcGx1Z2luIHJlZmVyZW5jZSBpbiBhIHBpcGVsaW5lJ3MgcHJvcHM6IGBzeW50aC5wbHVnaW5gLCB0aGVuIGVhY2hcbiAqIGBzdGFnZXNbXS5zdGVwc1tdLnBsdWdpbmAgaW4gb3JkZXIuIE9uZSBlbnRyeSBwZXIgU1RFUCAobm90IGRlLWR1cGxpY2F0ZWQpIOKAlFxuICogdGhlIGNvbnRyYWN0IHJlc3VsdCBpcyByZXBvcnRlZCBwZXIgc3RlcC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbGxlY3RQbHVnaW5TdGVwcyhwcm9wczogdW5rbm93bik6IFBsdWdpblN0ZXBSZWZbXSB7XG4gIGNvbnN0IHAgPSBhc1JlY29yZChwcm9wcyk7XG4gIGNvbnN0IG91dDogUGx1Z2luU3RlcFJlZltdID0gW107XG4gIGNvbnN0IHN5bnRoID0gdG9SZWYoYXNSZWNvcmQocC5zeW50aCkucGx1Z2luLCAnc3ludGgnLCAoKSA9PiAnc3ludGgnKTtcbiAgaWYgKHN5bnRoKSBvdXQucHVzaChzeW50aCk7XG4gIGNvbnN0IHN0YWdlcyA9IEFycmF5LmlzQXJyYXkocC5zdGFnZXMpID8gcC5zdGFnZXMgOiBbXTtcbiAgc3RhZ2VzLmZvckVhY2goKHN0YWdlLCBpKSA9PiB7XG4gICAgY29uc3QgcyA9IGFzUmVjb3JkKHN0YWdlKTtcbiAgICBjb25zdCBzdGFnZU5hbWUgPSB0eXBlb2Ygcy5zdGFnZU5hbWUgPT09ICdzdHJpbmcnID8gcy5zdGFnZU5hbWUgOiBgc3RhZ2UgJHtpICsgMX1gO1xuICAgIGNvbnN0IHN0ZXBzID0gQXJyYXkuaXNBcnJheShzLnN0ZXBzKSA/IHMuc3RlcHMgOiBbXTtcbiAgICBzdGVwcy5mb3JFYWNoKChzdGVwLCBqKSA9PiB7XG4gICAgICBjb25zdCByZWYgPSB0b1JlZihhc1JlY29yZChzdGVwKS5wbHVnaW4sIGBzdGFnZXNbJHtpfV0uc3RlcHNbJHtqfV1gLFxuICAgICAgICAobmFtZSwgYWxpYXMsIHB1Ymxpc2hlcikgPT4gYCR7c3RhZ2VOYW1lfS8ke2FsaWFzID8/IChwdWJsaXNoZXIgPyBgJHtwdWJsaXNoZXJ9LyR7bmFtZX1gIDogbmFtZSl9YCk7XG4gICAgICBpZiAocmVmKSBvdXQucHVzaChyZWYpO1xuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBUaGUgbG9va3VwIGZpbHRlciBzeW50aCBzZW5kcyBmb3IgYSByZWZlcmVuY2UgKHBpcGVsaW5lLW1hbmFnZXJcbiAqIGByZXNvbHZlUGx1Z2luc0ZvclByb3BzYCwgdGhlIGRlcGxveS10aW1lIGN1c3RvbSByZXNvdXJjZSwgdGhlIHBpcGVsaW5lXG4gKiBzZXJ2aWNlJ3MgY29udHJhY3QgY2hlY2spOiB0aGUgcmVmJ3MgbmFtZSDigJQgYW5kIGl0cyBgcHVibGlzaGVyYCwgd2hpY2hcbiAqIHJvdXRlcyB0aGUgbG9va3VwIHRvIHRoYXQgcHVibGlzaGVyJ3MgaW5zdGFsbGVkIGxpc3Rpbmcg4oCUIG92ZXJsYWlkIGJ5XG4gKiBhbiBleHBsaWNpdCBgZmlsdGVyYCAod2hvc2UgYG5hbWVgIHdpbnMpLCBlbHNlIHRoZSBkZWZhdWx0IGFjdGl2ZStkZWZhdWx0XG4gKiB2ZXJzaW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGx1Z2luTG9va3VwRmlsdGVyKHJlZjogUGljazxQbHVnaW5TdGVwUmVmLCAnbmFtZScgfCAnZmlsdGVyJyB8ICdwdWJsaXNoZXInPik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiByZWYubmFtZSxcbiAgICAuLi4ocmVmLnB1Ymxpc2hlciA/IHsgcHVibGlzaGVyOiByZWYucHVibGlzaGVyIH0gOiB7fSksXG4gICAgLi4uKHJlZi5maWx0ZXIgPz8geyBpc0FjdGl2ZTogdHJ1ZSwgaXNEZWZhdWx0OiB0cnVlIH0pLFxuICB9O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUmVmZXJlbmNlIGlkZW50aXR5IChDREstZnJlZTogdGhlIENMSSwgdGhlIHBpcGVsaW5lIHNlcnZpY2UgYW5kIHN5bnRoIHNoYXJlIGl0KVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBUaGUgcGx1Z2luLWFsaWFzIFNFR01FTlQgb2YgYW4gYXJ0aWZhY3Qga2V5IOKAlCBhbmQgdGhlIHJlc29sdmVyJ3MgY2FjaGUga2V5OlxuICogdGhlIGV4cGxpY2l0IGFsaWFzLCBvciBgJHtuYW1lfS1hbGlhc2Agd2hlbiB0aGVyZSBpcyBub25lXG4gKiAoYCR7cHVibGlzaGVyfS0ke25hbWV9LWFsaWFzYCBmb3IgYSBxdWFsaWZpZWQgcmVmZXJlbmNlKS4gVEhFIHJ1bGUg4oCUIHRoZSBmcm9udGVuZCdzIGFydGlmYWN0IHBpY2tlclxuICogKGBmcm9udGVuZC9zcmMvbGliL2FydGlmYWN0LWtleXMudHNgKSwgdGhlIENMSSdzIHByZS1yZXNvbHZlciBhbmRcbiAqIGBQbHVnaW5Mb29rdXAubm9ybWFsaXplYCBhbGwgYnVpbGQga2V5cyB0aGlzIHdheS5cbiAqXG4gKiBUaGUgcGxhY2VzIHRoYXQgUkVHSVNURVIga2V5cyBtdXN0IHVzZSBpdCB0b286IGEgc3RhZ2Ugc3RlcCByZWdpc3RlcmluZyB0aGVcbiAqIGJhcmUgbmFtZSAoYG5vZGVqcy1idWlsZGApIG9yIGEgc3ludGggc3RlcCBzdWZmaXhpbmcgYW4gZXhwbGljaXQgYWxpYXNcbiAqIChgbXktc3ludGgtYWxpYXNgKSB3b3VsZCBmYWlsIGFueSBVSS1waWNrZWQgaW5wdXQgYXJ0aWZhY3Qgd2l0aCBcIk5vIGFydGlmYWN0XG4gKiByZWdpc3RlcmVkXCIsIGJlY2F1c2UgdGhlIGtleSBpdCBhc2tzIGZvciBpcyBuZXZlciB0aGUga2V5IHRoYXQgd2FzIHN0b3JlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBsdWdpbkFydGlmYWN0QWxpYXMocGx1Z2luOiBQbHVnaW5SZWZJZGVudGl0eSk6IHN0cmluZyB7XG4gIGlmIChwbHVnaW4uYWxpYXMpIHJldHVybiBwbHVnaW4uYWxpYXM7XG4gIHJldHVybiBwbHVnaW4ucHVibGlzaGVyID8gYCR7c2FuaXRpemVQdWJsaXNoZXIocGx1Z2luLnB1Ymxpc2hlcil9LSR7cGx1Z2luLm5hbWV9LWFsaWFzYCA6IGAke3BsdWdpbi5uYW1lfS1hbGlhc2A7XG59XG5cbi8qKiBUaGUgZmllbGRzIG9mIGEgcGx1Z2luIFJFRkVSRU5DRSB0aGF0IGlkZW50aWZ5IGl0LiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5SZWZJZGVudGl0eSB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgYWxpYXM/OiBzdHJpbmc7XG4gIC8qKiBQdWJsaXNoZXIgaGFuZGxlIG9mIGFuIGluc3RhbGxlZCBsaXN0aW5nOyBhYnNlbnQgZm9yIGFuIHVucXVhbGlmaWVkIHJlZmVyZW5jZS4gKi9cbiAgcmVhZG9ubHkgcHVibGlzaGVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgcHVibGlzaGVyIGhhbmRsZSBhcyBpdCBtYXkgYXBwZWFyIGluIGEgY29uc3RydWN0IGlkIG9yIGEga2V5OiBvbmx5XG4gKiBgW0EtWmEtejAtOV8tXWAgKGhhbmRsZXMgYWxyZWFkeSBhcmU7IHRoaXMgaXMgdGhlIGd1YXJhbnRlZSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYW5pdGl6ZVB1Ymxpc2hlcihwdWJsaXNoZXI6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBwdWJsaXNoZXIucmVwbGFjZSgvW15BLVphLXowLTlfLV0vZywgJy0nKTtcbn1cblxuLyoqXG4gKiBUaGUgY29uc3RydWN0LWlkIHNlZ21lbnQgb2YgYSBwbHVnaW4gc3RlcDogdGhlIGV4cGxpY2l0IGFsaWFzLCBlbHNlXG4gKiBgPHB1Ymxpc2hlcj4tPG5hbWU+YCBmb3IgYSBxdWFsaWZpZWQgcmVmZXJlbmNlLCBlbHNlIHRoZSBiYXJlIG5hbWUg4oCUIHNvIGFcbiAqIHN0ZXAgdXNpbmcgYGFjbWVgJ3MgYGxpbnRgIGFuZCBvbmUgdXNpbmcgdGhlIG9yZydzIG93biBgbGludGAgbmV2ZXIgY29sbGlkZSxcbiAqIHdoaWxlIGFuIHVucXVhbGlmaWVkIHN0ZXAga2VlcHMgdGhlIGlkIGl0IGFsd2F5cyBoYWQgKHJlbmFtaW5nIGl0IHdvdWxkIG1ha2VcbiAqIENsb3VkRm9ybWF0aW9uIHJlcGxhY2UgaXRzIENvZGVCdWlsZCBwcm9qZWN0KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBsdWdpblN0ZXBJZEFsaWFzKHBsdWdpbjogUGx1Z2luUmVmSWRlbnRpdHkpOiBzdHJpbmcge1xuICAvLyBgPz9gLCBub3QgYHx8YDogYW4gZXhwbGljaXQgKGV2ZW4gZW1wdHkpIGFsaWFzIGtlZXBzIHRoZSBpZCBpdCBhbHdheXMgaGFkLlxuICByZXR1cm4gcGx1Z2luLmFsaWFzID8/IChwbHVnaW4ucHVibGlzaGVyID8gYCR7c2FuaXRpemVQdWJsaXNoZXIocGx1Z2luLnB1Ymxpc2hlcil9LSR7cGx1Z2luLm5hbWV9YCA6IHBsdWdpbi5uYW1lKTtcbn1cbiJdfQ==
@@ -0,0 +1,14 @@
1
+ import type { Plugin } from '@pipeline-builder/pipeline-data';
2
+ /**
3
+ * Unwrap a `/plugins/lookup` answer. The platform's success envelope is
4
+ * `{ success, statusCode, data: { plugin, warnings } }` (note the double
5
+ * nesting: `data.plugin`); `{ data: Plugin }`, `{ plugin }` and a bare Plugin
6
+ * are tolerated too. Returns the plugin (null when absent or nameless) and the
7
+ * lifecycle warning messages (deprecated / yanked-but-pinned) that ride beside it.
8
+ *
9
+ * Dependency-free (type-only imports) so the plugin-lookup Lambda can bundle it.
10
+ */
11
+ export declare function unwrapLookup(body: unknown): {
12
+ plugin: Plugin | null;
13
+ warnings: string[];
14
+ };
@@ -0,0 +1,29 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Unwrap a `/plugins/lookup` answer. The platform's success envelope is
5
+ * `{ success, statusCode, data: { plugin, warnings } }` (note the double
6
+ * nesting: `data.plugin`); `{ data: Plugin }`, `{ plugin }` and a bare Plugin
7
+ * are tolerated too. Returns the plugin (null when absent or nameless) and the
8
+ * lifecycle warning messages (deprecated / yanked-but-pinned) that ride beside it.
9
+ *
10
+ * Dependency-free (type-only imports) so the plugin-lookup Lambda can bundle it.
11
+ */
12
+ export function unwrapLookup(body) {
13
+ if (!body || typeof body !== 'object')
14
+ return { plugin: null, warnings: [] };
15
+ const inner = body.data;
16
+ const container = (inner && typeof inner === 'object' ? inner : body);
17
+ const candidate = container.plugin ?? container;
18
+ const plugin = candidate && typeof candidate === 'object' && typeof candidate.name === 'string'
19
+ && candidate.name.length > 0
20
+ ? candidate
21
+ : null;
22
+ const warnings = Array.isArray(container.warnings)
23
+ ? container.warnings
24
+ .map((w) => (w && typeof w === 'object' ? w.message : undefined))
25
+ .filter((m) => typeof m === 'string' && m.length > 0)
26
+ : [];
27
+ return { plugin, warnings };
28
+ }
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWxvb2t1cC1lbnZlbG9wZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL3BsdWdpbi1sb29rdXAtZW52ZWxvcGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUl0Qzs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsSUFBYTtJQUN4QyxJQUFJLENBQUMsSUFBSSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVE7UUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDN0UsTUFBTSxLQUFLLEdBQUksSUFBMkIsQ0FBQyxJQUFJLENBQUM7SUFDaEQsTUFBTSxTQUFTLEdBQUcsQ0FBQyxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBNkMsQ0FBQztJQUNsSCxNQUFNLFNBQVMsR0FBRyxTQUFTLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQztJQUNoRCxNQUFNLE1BQU0sR0FBRyxTQUFTLElBQUksT0FBTyxTQUFTLEtBQUssUUFBUSxJQUFJLE9BQVEsU0FBZ0MsQ0FBQyxJQUFJLEtBQUssUUFBUTtXQUNqSCxTQUE4QixDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUNsRCxDQUFDLENBQUMsU0FBbUI7UUFDckIsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNULE1BQU0sUUFBUSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQztRQUNoRCxDQUFDLENBQUMsU0FBUyxDQUFDLFFBQVE7YUFDakIsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFFLENBQTJCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQzthQUMzRixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQWUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztRQUNwRSxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ1AsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQztBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB0eXBlIHsgUGx1Z2luIH0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvcGlwZWxpbmUtZGF0YSc7XG5cbi8qKlxuICogVW53cmFwIGEgYC9wbHVnaW5zL2xvb2t1cGAgYW5zd2VyLiBUaGUgcGxhdGZvcm0ncyBzdWNjZXNzIGVudmVsb3BlIGlzXG4gKiBgeyBzdWNjZXNzLCBzdGF0dXNDb2RlLCBkYXRhOiB7IHBsdWdpbiwgd2FybmluZ3MgfSB9YCAobm90ZSB0aGUgZG91YmxlXG4gKiBuZXN0aW5nOiBgZGF0YS5wbHVnaW5gKTsgYHsgZGF0YTogUGx1Z2luIH1gLCBgeyBwbHVnaW4gfWAgYW5kIGEgYmFyZSBQbHVnaW5cbiAqIGFyZSB0b2xlcmF0ZWQgdG9vLiBSZXR1cm5zIHRoZSBwbHVnaW4gKG51bGwgd2hlbiBhYnNlbnQgb3IgbmFtZWxlc3MpIGFuZCB0aGVcbiAqIGxpZmVjeWNsZSB3YXJuaW5nIG1lc3NhZ2VzIChkZXByZWNhdGVkIC8geWFua2VkLWJ1dC1waW5uZWQpIHRoYXQgcmlkZSBiZXNpZGUgaXQuXG4gKlxuICogRGVwZW5kZW5jeS1mcmVlICh0eXBlLW9ubHkgaW1wb3J0cykgc28gdGhlIHBsdWdpbi1sb29rdXAgTGFtYmRhIGNhbiBidW5kbGUgaXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bndyYXBMb29rdXAoYm9keTogdW5rbm93bik6IHsgcGx1Z2luOiBQbHVnaW4gfCBudWxsOyB3YXJuaW5nczogc3RyaW5nW10gfSB7XG4gIGlmICghYm9keSB8fCB0eXBlb2YgYm9keSAhPT0gJ29iamVjdCcpIHJldHVybiB7IHBsdWdpbjogbnVsbCwgd2FybmluZ3M6IFtdIH07XG4gIGNvbnN0IGlubmVyID0gKGJvZHkgYXMgeyBkYXRhPzogdW5rbm93biB9KS5kYXRhO1xuICBjb25zdCBjb250YWluZXIgPSAoaW5uZXIgJiYgdHlwZW9mIGlubmVyID09PSAnb2JqZWN0JyA/IGlubmVyIDogYm9keSkgYXMgeyBwbHVnaW4/OiB1bmtub3duOyB3YXJuaW5ncz86IHVua25vd24gfTtcbiAgY29uc3QgY2FuZGlkYXRlID0gY29udGFpbmVyLnBsdWdpbiA/PyBjb250YWluZXI7XG4gIGNvbnN0IHBsdWdpbiA9IGNhbmRpZGF0ZSAmJiB0eXBlb2YgY2FuZGlkYXRlID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgKGNhbmRpZGF0ZSBhcyB7IG5hbWU/OiB1bmtub3duIH0pLm5hbWUgPT09ICdzdHJpbmcnXG4gICAgJiYgKGNhbmRpZGF0ZSBhcyB7IG5hbWU6IHN0cmluZyB9KS5uYW1lLmxlbmd0aCA+IDBcbiAgICA/IGNhbmRpZGF0ZSBhcyBQbHVnaW5cbiAgICA6IG51bGw7XG4gIGNvbnN0IHdhcm5pbmdzID0gQXJyYXkuaXNBcnJheShjb250YWluZXIud2FybmluZ3MpXG4gICAgPyBjb250YWluZXIud2FybmluZ3NcbiAgICAgIC5tYXAoKHcpID0+ICh3ICYmIHR5cGVvZiB3ID09PSAnb2JqZWN0JyA/ICh3IGFzIHsgbWVzc2FnZT86IHVua25vd24gfSkubWVzc2FnZSA6IHVuZGVmaW5lZCkpXG4gICAgICAuZmlsdGVyKChtKTogbSBpcyBzdHJpbmcgPT4gdHlwZW9mIG0gPT09ICdzdHJpbmcnICYmIG0ubGVuZ3RoID4gMClcbiAgICA6IFtdO1xuICByZXR1cm4geyBwbHVnaW4sIHdhcm5pbmdzIH07XG59XG4iXX0=
@@ -0,0 +1,50 @@
1
+ /**
2
+ * File the synth app writes the manifest to, inside the cloud assembly
3
+ * directory (`cdk deploy --output=<dir>`). The CLI reads it back after a
4
+ * successful deploy and forwards it on the registry POST.
5
+ */
6
+ export declare const STEP_MANIFEST_FILE = "pb-step-manifest.json";
7
+ /**
8
+ * `id` of every synthesized placeholder plugin (PluginLookup `fallback()` /
9
+ * `bootstrap()`) — a record standing in for a lookup that could not resolve at
10
+ * synth. Never a real `plugins` row, so the step manifest never records it.
11
+ */
12
+ export declare const PLACEHOLDER_PLUGIN_ID = "00000000-0000-0000-0000-000000000000";
13
+ /**
14
+ * One manifest entry as the synth records it. Carries the resolved plugin
15
+ * record's id so the pipeline service can re-resolve the authoritative
16
+ * name/version/digest/owner itself — the CLI's claim is never trusted for
17
+ * anything that feeds cross-org stats (publisher, verified use).
18
+ */
19
+ export interface StepManifestEntry {
20
+ /** CodePipeline stage name, as the built pipeline names it. */
21
+ readonly stageName: string;
22
+ /** CodePipeline action name, as the built pipeline names it. */
23
+ readonly actionName: string;
24
+ /** `plugins.id` of the resolved plugin record. */
25
+ readonly pluginId: string;
26
+ readonly pluginName: string;
27
+ readonly pluginVersion: string;
28
+ /** Signed image digest the step is pinned to; null for image-less plugins. */
29
+ readonly imageDigest: string | null;
30
+ }
31
+ /** The plugin fields {@link pluginImageRepository} reads. */
32
+ export interface PluginImageRef {
33
+ readonly orgId: string;
34
+ readonly name: string;
35
+ readonly buildType?: string | null;
36
+ }
37
+ /**
38
+ * Registry repository an org-owned plugin ROW's image lives at
39
+ * (`<namespace>/<name>`, no host, no digest): the system org's under
40
+ * `system/`, a tenant's under `org-<orgId>/`. Must match the push side
41
+ * (api/plugin `pluginUri`). Returns null for a `metadata_only` plugin.
42
+ *
43
+ * Only for rows the caller's org resolves as its OWN (or its parent's): the
44
+ * plugin lookup stamps it as the record's `imageRepository`. A listed plugin's
45
+ * repository is its listing version's `public/<publisher>/<name>` copy —
46
+ * synth never derives a repository itself.
47
+ */
48
+ export declare function pluginImageRepository(plugin: PluginImageRef): string | null;
49
+ /** A plugin image repository lookup may return: `public/<publisher>/<name>`, `org-<id>/<name>` or `system/<name>`. */
50
+ export declare const PLUGIN_IMAGE_REPOSITORY_RE: RegExp;
@@ -0,0 +1,47 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Step manifest: which plugin each CodePipeline action
5
+ * of a deployed pipeline runs. CDK-free half — the shapes and helpers shared by
6
+ * the synth (which records it, see `pipeline/step-manifest-recorder.ts`), the
7
+ * CLI (which ships it with the registry registration) and the pipeline service
8
+ * (which validates and stores it in `pipeline_step_manifests`).
9
+ *
10
+ * Event ingest joins `pipeline_events` on (pipeline_id, stage_name,
11
+ * action_name), so `stageName`/`actionName` here are read off the BUILT
12
+ * CodePipeline, never recomputed from our own ids — they are exactly the names
13
+ * CodePipeline state-change events report.
14
+ */
15
+ import { SYSTEM_ORG_ID } from '@pipeline-builder/api-core';
16
+ /**
17
+ * File the synth app writes the manifest to, inside the cloud assembly
18
+ * directory (`cdk deploy --output=<dir>`). The CLI reads it back after a
19
+ * successful deploy and forwards it on the registry POST.
20
+ */
21
+ export const STEP_MANIFEST_FILE = 'pb-step-manifest.json';
22
+ /**
23
+ * `id` of every synthesized placeholder plugin (PluginLookup `fallback()` /
24
+ * `bootstrap()`) — a record standing in for a lookup that could not resolve at
25
+ * synth. Never a real `plugins` row, so the step manifest never records it.
26
+ */
27
+ export const PLACEHOLDER_PLUGIN_ID = '00000000-0000-0000-0000-000000000000';
28
+ /**
29
+ * Registry repository an org-owned plugin ROW's image lives at
30
+ * (`<namespace>/<name>`, no host, no digest): the system org's under
31
+ * `system/`, a tenant's under `org-<orgId>/`. Must match the push side
32
+ * (api/plugin `pluginUri`). Returns null for a `metadata_only` plugin.
33
+ *
34
+ * Only for rows the caller's org resolves as its OWN (or its parent's): the
35
+ * plugin lookup stamps it as the record's `imageRepository`. A listed plugin's
36
+ * repository is its listing version's `public/<publisher>/<name>` copy —
37
+ * synth never derives a repository itself.
38
+ */
39
+ export function pluginImageRepository(plugin) {
40
+ if (plugin.buildType === 'metadata_only')
41
+ return null;
42
+ const namespace = plugin.orgId === SYSTEM_ORG_ID ? 'system' : `org-${plugin.orgId}`;
43
+ return `${namespace}/${plugin.name}`;
44
+ }
45
+ /** A plugin image repository lookup may return: `public/<publisher>/<name>`, `org-<id>/<name>` or `system/<name>`. */
46
+ export const PLUGIN_IMAGE_REPOSITORY_RE = /^(?:public\/[a-z0-9]+(?:-[a-z0-9]+)*|org-[a-z0-9][a-z0-9-]*|system)\/[a-z0-9][a-z0-9._-]*$/;
47
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1tYW5pZmVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL3N0ZXAtbWFuaWZlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7R0FXRztBQUVILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUUzRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsdUJBQXVCLENBQUM7QUFFMUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLHNDQUFzQyxDQUFDO0FBNEI1RTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQixDQUFDLE1BQXNCO0lBQzFELElBQUksTUFBTSxDQUFDLFNBQVMsS0FBSyxlQUFlO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDdEQsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLEtBQUssS0FBSyxhQUFhLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDcEYsT0FBTyxHQUFHLFNBQVMsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDdkMsQ0FBQztBQUVELHNIQUFzSDtBQUN0SCxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyw0RkFBNEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFN0ZXAgbWFuaWZlc3Q6IHdoaWNoIHBsdWdpbiBlYWNoIENvZGVQaXBlbGluZSBhY3Rpb25cbiAqIG9mIGEgZGVwbG95ZWQgcGlwZWxpbmUgcnVucy4gQ0RLLWZyZWUgaGFsZiDigJQgdGhlIHNoYXBlcyBhbmQgaGVscGVycyBzaGFyZWQgYnlcbiAqIHRoZSBzeW50aCAod2hpY2ggcmVjb3JkcyBpdCwgc2VlIGBwaXBlbGluZS9zdGVwLW1hbmlmZXN0LXJlY29yZGVyLnRzYCksIHRoZVxuICogQ0xJICh3aGljaCBzaGlwcyBpdCB3aXRoIHRoZSByZWdpc3RyeSByZWdpc3RyYXRpb24pIGFuZCB0aGUgcGlwZWxpbmUgc2VydmljZVxuICogKHdoaWNoIHZhbGlkYXRlcyBhbmQgc3RvcmVzIGl0IGluIGBwaXBlbGluZV9zdGVwX21hbmlmZXN0c2ApLlxuICpcbiAqIEV2ZW50IGluZ2VzdCBqb2lucyBgcGlwZWxpbmVfZXZlbnRzYCBvbiAocGlwZWxpbmVfaWQsIHN0YWdlX25hbWUsXG4gKiBhY3Rpb25fbmFtZSksIHNvIGBzdGFnZU5hbWVgL2BhY3Rpb25OYW1lYCBoZXJlIGFyZSByZWFkIG9mZiB0aGUgQlVJTFRcbiAqIENvZGVQaXBlbGluZSwgbmV2ZXIgcmVjb21wdXRlZCBmcm9tIG91ciBvd24gaWRzIOKAlCB0aGV5IGFyZSBleGFjdGx5IHRoZSBuYW1lc1xuICogQ29kZVBpcGVsaW5lIHN0YXRlLWNoYW5nZSBldmVudHMgcmVwb3J0LlxuICovXG5cbmltcG9ydCB7IFNZU1RFTV9PUkdfSUQgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5cbi8qKlxuICogRmlsZSB0aGUgc3ludGggYXBwIHdyaXRlcyB0aGUgbWFuaWZlc3QgdG8sIGluc2lkZSB0aGUgY2xvdWQgYXNzZW1ibHlcbiAqIGRpcmVjdG9yeSAoYGNkayBkZXBsb3kgLS1vdXRwdXQ9PGRpcj5gKS4gVGhlIENMSSByZWFkcyBpdCBiYWNrIGFmdGVyIGFcbiAqIHN1Y2Nlc3NmdWwgZGVwbG95IGFuZCBmb3J3YXJkcyBpdCBvbiB0aGUgcmVnaXN0cnkgUE9TVC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNURVBfTUFOSUZFU1RfRklMRSA9ICdwYi1zdGVwLW1hbmlmZXN0Lmpzb24nO1xuXG4vKipcbiAqIGBpZGAgb2YgZXZlcnkgc3ludGhlc2l6ZWQgcGxhY2Vob2xkZXIgcGx1Z2luIChQbHVnaW5Mb29rdXAgYGZhbGxiYWNrKClgIC9cbiAqIGBib290c3RyYXAoKWApIOKAlCBhIHJlY29yZCBzdGFuZGluZyBpbiBmb3IgYSBsb29rdXAgdGhhdCBjb3VsZCBub3QgcmVzb2x2ZSBhdFxuICogc3ludGguIE5ldmVyIGEgcmVhbCBgcGx1Z2luc2Agcm93LCBzbyB0aGUgc3RlcCBtYW5pZmVzdCBuZXZlciByZWNvcmRzIGl0LlxuICovXG5leHBvcnQgY29uc3QgUExBQ0VIT0xERVJfUExVR0lOX0lEID0gJzAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCc7XG5cbi8qKlxuICogT25lIG1hbmlmZXN0IGVudHJ5IGFzIHRoZSBzeW50aCByZWNvcmRzIGl0LiBDYXJyaWVzIHRoZSByZXNvbHZlZCBwbHVnaW5cbiAqIHJlY29yZCdzIGlkIHNvIHRoZSBwaXBlbGluZSBzZXJ2aWNlIGNhbiByZS1yZXNvbHZlIHRoZSBhdXRob3JpdGF0aXZlXG4gKiBuYW1lL3ZlcnNpb24vZGlnZXN0L293bmVyIGl0c2VsZiDigJQgdGhlIENMSSdzIGNsYWltIGlzIG5ldmVyIHRydXN0ZWQgZm9yXG4gKiBhbnl0aGluZyB0aGF0IGZlZWRzIGNyb3NzLW9yZyBzdGF0cyAocHVibGlzaGVyLCB2ZXJpZmllZCB1c2UpLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0ZXBNYW5pZmVzdEVudHJ5IHtcbiAgLyoqIENvZGVQaXBlbGluZSBzdGFnZSBuYW1lLCBhcyB0aGUgYnVpbHQgcGlwZWxpbmUgbmFtZXMgaXQuICovXG4gIHJlYWRvbmx5IHN0YWdlTmFtZTogc3RyaW5nO1xuICAvKiogQ29kZVBpcGVsaW5lIGFjdGlvbiBuYW1lLCBhcyB0aGUgYnVpbHQgcGlwZWxpbmUgbmFtZXMgaXQuICovXG4gIHJlYWRvbmx5IGFjdGlvbk5hbWU6IHN0cmluZztcbiAgLyoqIGBwbHVnaW5zLmlkYCBvZiB0aGUgcmVzb2x2ZWQgcGx1Z2luIHJlY29yZC4gKi9cbiAgcmVhZG9ubHkgcGx1Z2luSWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgcGx1Z2luTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBwbHVnaW5WZXJzaW9uOiBzdHJpbmc7XG4gIC8qKiBTaWduZWQgaW1hZ2UgZGlnZXN0IHRoZSBzdGVwIGlzIHBpbm5lZCB0bzsgbnVsbCBmb3IgaW1hZ2UtbGVzcyBwbHVnaW5zLiAqL1xuICByZWFkb25seSBpbWFnZURpZ2VzdDogc3RyaW5nIHwgbnVsbDtcbn1cblxuLyoqIFRoZSBwbHVnaW4gZmllbGRzIHtAbGluayBwbHVnaW5JbWFnZVJlcG9zaXRvcnl9IHJlYWRzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5JbWFnZVJlZiB7XG4gIHJlYWRvbmx5IG9yZ0lkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgYnVpbGRUeXBlPzogc3RyaW5nIHwgbnVsbDtcbn1cblxuLyoqXG4gKiBSZWdpc3RyeSByZXBvc2l0b3J5IGFuIG9yZy1vd25lZCBwbHVnaW4gUk9XJ3MgaW1hZ2UgbGl2ZXMgYXRcbiAqIChgPG5hbWVzcGFjZT4vPG5hbWU+YCwgbm8gaG9zdCwgbm8gZGlnZXN0KTogdGhlIHN5c3RlbSBvcmcncyB1bmRlclxuICogYHN5c3RlbS9gLCBhIHRlbmFudCdzIHVuZGVyIGBvcmctPG9yZ0lkPi9gLiBNdXN0IG1hdGNoIHRoZSBwdXNoIHNpZGVcbiAqIChhcGkvcGx1Z2luIGBwbHVnaW5VcmlgKS4gUmV0dXJucyBudWxsIGZvciBhIGBtZXRhZGF0YV9vbmx5YCBwbHVnaW4uXG4gKlxuICogT25seSBmb3Igcm93cyB0aGUgY2FsbGVyJ3Mgb3JnIHJlc29sdmVzIGFzIGl0cyBPV04gKG9yIGl0cyBwYXJlbnQncyk6IHRoZVxuICogcGx1Z2luIGxvb2t1cCBzdGFtcHMgaXQgYXMgdGhlIHJlY29yZCdzIGBpbWFnZVJlcG9zaXRvcnlgLiBBIGxpc3RlZCBwbHVnaW4nc1xuICogcmVwb3NpdG9yeSBpcyBpdHMgbGlzdGluZyB2ZXJzaW9uJ3MgYHB1YmxpYy88cHVibGlzaGVyPi88bmFtZT5gIGNvcHkg4oCUXG4gKiBzeW50aCBuZXZlciBkZXJpdmVzIGEgcmVwb3NpdG9yeSBpdHNlbGYuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwbHVnaW5JbWFnZVJlcG9zaXRvcnkocGx1Z2luOiBQbHVnaW5JbWFnZVJlZik6IHN0cmluZyB8IG51bGwge1xuICBpZiAocGx1Z2luLmJ1aWxkVHlwZSA9PT0gJ21ldGFkYXRhX29ubHknKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbmFtZXNwYWNlID0gcGx1Z2luLm9yZ0lkID09PSBTWVNURU1fT1JHX0lEID8gJ3N5c3RlbScgOiBgb3JnLSR7cGx1Z2luLm9yZ0lkfWA7XG4gIHJldHVybiBgJHtuYW1lc3BhY2V9LyR7cGx1Z2luLm5hbWV9YDtcbn1cblxuLyoqIEEgcGx1Z2luIGltYWdlIHJlcG9zaXRvcnkgbG9va3VwIG1heSByZXR1cm46IGBwdWJsaWMvPHB1Ymxpc2hlcj4vPG5hbWU+YCwgYG9yZy08aWQ+LzxuYW1lPmAgb3IgYHN5c3RlbS88bmFtZT5gLiAqL1xuZXhwb3J0IGNvbnN0IFBMVUdJTl9JTUFHRV9SRVBPU0lUT1JZX1JFID0gL14oPzpwdWJsaWNcXC9bYS16MC05XSsoPzotW2EtejAtOV0rKSp8b3JnLVthLXowLTldW2EtejAtOS1dKnxzeXN0ZW0pXFwvW2EtejAtOV1bYS16MC05Ll8tXSokLztcbiJdfQ==
@@ -0,0 +1,47 @@
1
+ import { SecretsManagerClient } from '@aws-sdk/client-secrets-manager';
2
+ /**
3
+ * The platform credential a deployed Lambda holds: an opaque service-account key
4
+ * (`pb_sa_…`), stored in the `password` field of the Secrets Manager secret that
5
+ * `pipeline-manager infra store-token` writes. `password` stays the canonical
6
+ * field because CodeBuild's `secretsManagerCredentials` reads the same one.
7
+ *
8
+ * Dependency-free apart from the Secrets Manager client so every Lambda bundle
9
+ * can import it without dragging in aws-cdk-lib.
10
+ */
11
+ /** Access-key prefixes platform issues. A stored JWT is NOT one of these. */
12
+ export declare const ACCESS_KEY_PREFIXES: readonly string[];
13
+ /** True for an HTTP status that means "this credential was refused". */
14
+ export declare function isCredentialRefusal(status: number | undefined): boolean;
15
+ /**
16
+ * Refuse anything that is not an opaque access key, naming where it came from.
17
+ * A stored JWT would otherwise surface much later as an opaque 401 from the API,
18
+ * several layers away from the secret an operator has to fix.
19
+ */
20
+ export declare function assertAccessKey(value: string, source: string): void;
21
+ /** Read and parse a Secrets Manager secret holding a JSON credential record. */
22
+ export declare function readCredentialSecret<T extends Record<string, unknown>>(secretName: string, client?: Pick<SecretsManagerClient, 'send'>): Promise<T>;
23
+ /** Read the `pb_sa_…` key from a credential secret, refusing a missing or non-key value. */
24
+ export declare function readAccessKeyFromSecret(secretName: string): Promise<string>;
25
+ export interface PlatformCredential {
26
+ /** The cached key, read from the secret on first use (or after {@link invalidate}). */
27
+ getKey(): Promise<string>;
28
+ /**
29
+ * Forget the cached key after the API refused it (401/403). The token-renew
30
+ * Lambda rotates the secret and then revokes the predecessor, so a warm
31
+ * container that kept its cached key would present the retired one forever.
32
+ * The next {@link getKey} re-reads the secret and picks up the replacement.
33
+ */
34
+ invalidate(): void;
35
+ /** Forget everything, including an env-provided key (tests). */
36
+ reset(): void;
37
+ }
38
+ /**
39
+ * A per-container cached platform credential. `envKeyVar` names an optional env
40
+ * var holding the key directly; an env-provided key cannot change without a new
41
+ * container, so {@link PlatformCredential.invalidate} keeps it.
42
+ */
43
+ export declare function createPlatformCredential(opts: {
44
+ /** The secret name, or a getter read at first use (env set after module load). */
45
+ secretName?: string | (() => string | undefined);
46
+ envKeyVar?: string;
47
+ }): PlatformCredential;