@forgezero/access 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/principal.js CHANGED
@@ -59,14 +59,42 @@ function defineFactors(factors) {
59
59
  }
60
60
  return factors;
61
61
  }
62
+ var ROUTE_LIFECYCLE_STATES = ["active", "deprecated", "retired"];
62
63
  function page(label, options = {}) {
63
- return { kind: "page", label, accessGroup: "default", ...options };
64
+ return {
65
+ kind: "page",
66
+ label,
67
+ accessGroup: "default",
68
+ lifecycle: { version: 1, status: "active", introducedAt: "initial" },
69
+ ...options
70
+ };
64
71
  }
65
72
  function action(label, method, options = {}) {
66
- return { kind: "action", label, method, accessGroup: "default", ...options };
73
+ return {
74
+ kind: "action",
75
+ label,
76
+ method,
77
+ accessGroup: "default",
78
+ lifecycle: { version: 1, status: "active", introducedAt: "initial" },
79
+ ...options
80
+ };
67
81
  }
68
82
  function defineRoutes(routes) {
69
83
  for (const [key, route] of Object.entries(routes)) {
84
+ const lifecycle = route.lifecycle;
85
+ if (!Number.isSafeInteger(lifecycle.version) || lifecycle.version < 1) {
86
+ throw new AccessError("ROUTE_VERSION_INVALID", `"${key}": route version must be a positive integer.`);
87
+ }
88
+ const validTimestamp = (value) => Number.isFinite(Date.parse(value));
89
+ if (lifecycle.introducedAt !== "initial" && !validTimestamp(lifecycle.introducedAt)) {
90
+ throw new AccessError("ROUTE_LIFECYCLE_INVALID", `"${key}": introducedAt must be an ISO timestamp or initial.`);
91
+ }
92
+ if (lifecycle.status === "deprecated" && (!validTimestamp(lifecycle.deprecatedAt) || !validTimestamp(lifecycle.expiresAt) || Date.parse(lifecycle.deprecatedAt) > Date.parse(lifecycle.expiresAt) || lifecycle.replacement === key)) {
93
+ throw new AccessError("ROUTE_LIFECYCLE_INVALID", `"${key}": deprecated route lifecycle is invalid.`);
94
+ }
95
+ if (lifecycle.status === "retired" && (!validTimestamp(lifecycle.retiredAt) || lifecycle.replacement === key)) {
96
+ throw new AccessError("ROUTE_LIFECYCLE_INVALID", `"${key}": retired route lifecycle is invalid.`);
97
+ }
70
98
  if (!/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/.test(route.accessGroup)) {
71
99
  throw new AccessError("ROUTE_ACCESS_INVALID", `"${key}": accessGroup must be a bounded name.`);
72
100
  }
@@ -224,6 +252,10 @@ function defineAccessControl(config) {
224
252
  const route = config.routes[key];
225
253
  if (!route)
226
254
  return false;
255
+ if (route.lifecycle?.status === "retired")
256
+ return false;
257
+ if (route.lifecycle?.status === "deprecated" && Date.parse(context?.now ?? new Date().toISOString()) >= Date.parse(route.lifecycle.expiresAt))
258
+ return false;
227
259
  if (route.feature && !features.includes(route.feature))
228
260
  return false;
229
261
  if (context?.stage && route.stages && !route.stages.includes(context.stage))
@@ -275,7 +307,7 @@ function impactOfDisabling(access, enabledAfter) {
275
307
  }
276
308
  return broken;
277
309
  }
278
- var VERSION = "0.1.13";
310
+ var VERSION = "0.1.15";
279
311
 
280
312
  // src/principal.ts
281
313
  var ATOM = /^[A-Za-z0-9][A-Za-z0-9_.:@/-]{0,255}$/;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Dependency-free JSON-Schema SSOT primitives for request and response
3
+ * boundaries. A contract is declared once as data and its TypeScript type is
4
+ * inferred from that same value; consumers must not repeat the wire shape in
5
+ * an interface or type alias.
6
+ */
7
+ declare const contractType: unique symbol;
8
+ declare const optionalProperty: unique symbol;
9
+ export type ContractSchema<Value = unknown> = Readonly<Record<string, unknown>> & {
10
+ readonly [contractType]?: Value;
11
+ };
12
+ export type Infer<Schema extends ContractSchema> = Schema extends ContractSchema<infer Value> ? Value : never;
13
+ export type OptionalSchema<Schema extends ContractSchema> = Schema & {
14
+ readonly [optionalProperty]: true;
15
+ };
16
+ type PropertyValue<Schema extends ContractSchema> = Infer<Schema>;
17
+ type RequiredPropertyKeys<Properties extends Readonly<Record<string, ContractSchema>>> = {
18
+ [Key in keyof Properties]-?: Properties[Key] extends OptionalSchema<ContractSchema> ? never : Key;
19
+ }[keyof Properties];
20
+ type OptionalPropertyKeys<Properties extends Readonly<Record<string, ContractSchema>>> = Exclude<keyof Properties, RequiredPropertyKeys<Properties>>;
21
+ type ObjectValue<Properties extends Readonly<Record<string, ContractSchema>>> = {
22
+ [Key in RequiredPropertyKeys<Properties>]: PropertyValue<Properties[Key]>;
23
+ } & {
24
+ [Key in OptionalPropertyKeys<Properties>]?: PropertyValue<Properties[Key]>;
25
+ };
26
+ export type ContractIssue = Readonly<{
27
+ path: string;
28
+ expected: string;
29
+ }>;
30
+ export type ContractParseResult<Value> = Readonly<{
31
+ ok: true;
32
+ value: Value;
33
+ }> | Readonly<{
34
+ ok: false;
35
+ issues: readonly ContractIssue[];
36
+ }>;
37
+ type StringOptions = Readonly<{
38
+ minLength?: number;
39
+ maxLength?: number;
40
+ pattern?: string;
41
+ format?: string;
42
+ }>;
43
+ type NumberOptions = Readonly<{
44
+ minimum?: number;
45
+ maximum?: number;
46
+ }>;
47
+ type ArrayOptions = Readonly<{
48
+ minItems?: number;
49
+ maxItems?: number;
50
+ uniqueItems?: boolean;
51
+ }>;
52
+ type ObjectOptions = Readonly<{
53
+ additionalProperties?: boolean;
54
+ }>;
55
+ type RecordOptions = Readonly<{
56
+ minProperties?: number;
57
+ maxProperties?: number;
58
+ keyPattern?: string;
59
+ }>;
60
+ export declare const schema: Readonly<{
61
+ unknown: () => ContractSchema<unknown>;
62
+ string: (options?: StringOptions) => ContractSchema<string>;
63
+ number: (options?: NumberOptions) => ContractSchema<number>;
64
+ integer: (options?: NumberOptions) => ContractSchema<number>;
65
+ boolean: () => ContractSchema<boolean>;
66
+ null: () => ContractSchema<null>;
67
+ literal: <const Value extends string | number | boolean | null>(value: Value) => ContractSchema<Value>;
68
+ optional: <Schema extends ContractSchema>(value: Schema) => OptionalSchema<Schema>;
69
+ array: <Schema extends ContractSchema>(items: Schema, options?: ArrayOptions) => ContractSchema<Array<Infer<Schema>>>;
70
+ union: <const Schemas extends readonly ContractSchema[]>(...members: Schemas) => ContractSchema<Infer<Schemas[number]>>;
71
+ object: <const Properties extends Readonly<Record<string, ContractSchema>>>(properties: Properties, options?: ObjectOptions) => ContractSchema<ObjectValue<Properties>>;
72
+ record: <Schema extends ContractSchema>(values: Schema, options?: RecordOptions) => ContractSchema<Record<string, Infer<Schema>>>;
73
+ }>;
74
+ export declare function extend<Base extends ContractSchema<Record<string, unknown>>, Extension extends ContractSchema<Record<string, unknown>>>(base: Base, extension: Extension): ContractSchema<Infer<Base> & Infer<Extension>>;
75
+ export declare function pick<Source extends ContractSchema<Record<string, unknown>>, const Keys extends readonly (keyof Infer<Source> & string)[]>(source: Source, keys: Keys): ContractSchema<Pick<Infer<Source>, Keys[number]>>;
76
+ export declare function omit<Source extends ContractSchema<Record<string, unknown>>, const Keys extends readonly (keyof Infer<Source> & string)[]>(source: Source, keys: Keys): ContractSchema<Omit<Infer<Source>, Keys[number]>>;
77
+ export declare function parse<Schema extends ContractSchema>(contract: Schema, value: unknown): ContractParseResult<Infer<Schema>>;
78
+ export {};
package/dist/schema.js ADDED
@@ -0,0 +1,171 @@
1
+ // src/schema.ts
2
+ var contractType = Symbol("forgezero.contract.type");
3
+ var optionalProperty = Symbol("forgezero.contract.optional");
4
+ function freeze(schema) {
5
+ return Object.freeze(schema);
6
+ }
7
+ var schema = Object.freeze({
8
+ unknown: () => freeze({}),
9
+ string: (options = {}) => freeze({ type: "string", ...options }),
10
+ number: (options = {}) => freeze({ type: "number", ...options }),
11
+ integer: (options = {}) => freeze({ type: "integer", ...options }),
12
+ boolean: () => freeze({ type: "boolean" }),
13
+ null: () => freeze({ type: "null" }),
14
+ literal: (value) => freeze({ const: value }),
15
+ optional: (value) => Object.freeze({ ...value, [optionalProperty]: true }),
16
+ array: (items, options = {}) => freeze({ type: "array", items, ...options }),
17
+ union: (...members) => freeze({ anyOf: members }),
18
+ object: (properties, options = { additionalProperties: false }) => {
19
+ const required = Object.entries(properties).filter(([, value]) => !(optionalProperty in value)).map(([key]) => key);
20
+ const cleanProperties = Object.fromEntries(Object.entries(properties).map(([key, value]) => {
21
+ if (!(optionalProperty in value))
22
+ return [key, value];
23
+ const { [optionalProperty]: _, ...clean } = value;
24
+ return [key, clean];
25
+ }));
26
+ return freeze({ type: "object", properties: cleanProperties, required, ...options });
27
+ },
28
+ record: (values, options = {}) => freeze({
29
+ type: "object",
30
+ properties: {},
31
+ additionalProperties: values,
32
+ ...options.minProperties === undefined ? {} : { minProperties: options.minProperties },
33
+ ...options.maxProperties === undefined ? {} : { maxProperties: options.maxProperties },
34
+ ...options.keyPattern === undefined ? {} : { propertyNames: { pattern: options.keyPattern } }
35
+ })
36
+ });
37
+ function extend(base, extension) {
38
+ const baseProperties = base.properties ?? {};
39
+ const extensionProperties = extension.properties ?? {};
40
+ const required = [...new Set([
41
+ ...base.required ?? [],
42
+ ...extension.required ?? []
43
+ ])];
44
+ return freeze({
45
+ type: "object",
46
+ properties: { ...baseProperties, ...extensionProperties },
47
+ required,
48
+ additionalProperties: false
49
+ });
50
+ }
51
+ function pick(source, keys) {
52
+ const sourceProperties = source.properties ?? {};
53
+ const selected = Object.fromEntries(keys.map((key) => [key, sourceProperties[key]]));
54
+ const required = (source.required ?? []).filter((key) => keys.includes(key));
55
+ return freeze({ type: "object", properties: selected, required, additionalProperties: false });
56
+ }
57
+ function omit(source, keys) {
58
+ const omitted = new Set(keys);
59
+ const sourceProperties = source.properties ?? {};
60
+ const selected = Object.fromEntries(Object.entries(sourceProperties).filter(([key]) => !omitted.has(key)));
61
+ const required = (source.required ?? []).filter((key) => !omitted.has(key));
62
+ return freeze({ type: "object", properties: selected, required, additionalProperties: false });
63
+ }
64
+ var record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
65
+ function validate(current, value, path, issues) {
66
+ if (issues.length >= 32)
67
+ return false;
68
+ if ("const" in current) {
69
+ const valid = value === current.const;
70
+ if (!valid)
71
+ issues.push({ path, expected: JSON.stringify(current.const) });
72
+ return valid;
73
+ }
74
+ if (Array.isArray(current.anyOf)) {
75
+ for (const member of current.anyOf) {
76
+ const candidate = [];
77
+ if (validate(member, value, path, candidate))
78
+ return true;
79
+ }
80
+ issues.push({ path, expected: "one declared union member" });
81
+ return false;
82
+ }
83
+ if (current.type === "string") {
84
+ const valid = typeof value === "string" && (typeof current.minLength !== "number" || value.length >= current.minLength) && (typeof current.maxLength !== "number" || value.length <= current.maxLength) && (typeof current.pattern !== "string" || new RegExp(current.pattern).test(value));
85
+ if (!valid)
86
+ issues.push({ path, expected: "declared string" });
87
+ return valid;
88
+ }
89
+ if (current.type === "number" || current.type === "integer") {
90
+ const valid = typeof value === "number" && Number.isFinite(value) && (current.type !== "integer" || Number.isSafeInteger(value)) && (typeof current.minimum !== "number" || value >= current.minimum) && (typeof current.maximum !== "number" || value <= current.maximum);
91
+ if (!valid)
92
+ issues.push({ path, expected: `declared ${String(current.type)}` });
93
+ return valid;
94
+ }
95
+ if (current.type === "boolean" || current.type === "null") {
96
+ const valid = current.type === "boolean" ? typeof value === "boolean" : value === null;
97
+ if (!valid)
98
+ issues.push({ path, expected: String(current.type) });
99
+ return valid;
100
+ }
101
+ if (current.type === "array") {
102
+ if (!Array.isArray(value)) {
103
+ issues.push({ path, expected: "array" });
104
+ return false;
105
+ }
106
+ let valid = (typeof current.minItems !== "number" || value.length >= current.minItems) && (typeof current.maxItems !== "number" || value.length <= current.maxItems);
107
+ if (current.uniqueItems === true && new Set(value.map((entry) => JSON.stringify(entry))).size !== value.length)
108
+ valid = false;
109
+ if (!valid)
110
+ issues.push({ path, expected: "bounded declared array" });
111
+ for (let index = 0;index < value.length && issues.length < 32; index += 1) {
112
+ valid = validate(current.items, value[index], `${path}[${index}]`, issues) && valid;
113
+ }
114
+ return valid;
115
+ }
116
+ if (current.type === "object") {
117
+ if (!record(value)) {
118
+ issues.push({ path, expected: "object" });
119
+ return false;
120
+ }
121
+ const properties = current.properties ?? {};
122
+ const required = new Set(current.required ?? []);
123
+ let valid = (typeof current.minProperties !== "number" || Object.keys(value).length >= current.minProperties) && (typeof current.maxProperties !== "number" || Object.keys(value).length <= current.maxProperties);
124
+ if (!valid)
125
+ issues.push({ path, expected: "bounded property count" });
126
+ const keyPattern = current.propertyNames?.pattern;
127
+ if (typeof keyPattern === "string") {
128
+ for (const key of Object.keys(value))
129
+ if (!new RegExp(keyPattern).test(key)) {
130
+ issues.push({ path: `${path}.${key}`, expected: "declared property name" });
131
+ valid = false;
132
+ }
133
+ }
134
+ for (const key of required) {
135
+ if (!(key in value)) {
136
+ issues.push({ path: `${path}.${key}`, expected: "required property" });
137
+ valid = false;
138
+ }
139
+ }
140
+ if (current.additionalProperties === false) {
141
+ for (const key of Object.keys(value)) {
142
+ if (!(key in properties)) {
143
+ issues.push({ path: `${path}.${key}`, expected: "no additional property" });
144
+ valid = false;
145
+ }
146
+ }
147
+ } else if (record(current.additionalProperties)) {
148
+ for (const [key, child] of Object.entries(value)) {
149
+ if (!(key in properties))
150
+ valid = validate(current.additionalProperties, child, `${path}.${key}`, issues) && valid;
151
+ }
152
+ }
153
+ for (const [key, child] of Object.entries(properties)) {
154
+ if (key in value)
155
+ valid = validate(child, value[key], `${path}.${key}`, issues) && valid;
156
+ }
157
+ return valid;
158
+ }
159
+ return true;
160
+ }
161
+ function parse(contract, value) {
162
+ const issues = [];
163
+ return validate(contract, value, "$", issues) ? { ok: true, value } : { ok: false, issues };
164
+ }
165
+ export {
166
+ schema,
167
+ pick,
168
+ parse,
169
+ omit,
170
+ extend
171
+ };
package/dist/testing.js CHANGED
@@ -59,14 +59,42 @@ function defineFactors(factors) {
59
59
  }
60
60
  return factors;
61
61
  }
62
+ var ROUTE_LIFECYCLE_STATES = ["active", "deprecated", "retired"];
62
63
  function page(label, options = {}) {
63
- return { kind: "page", label, accessGroup: "default", ...options };
64
+ return {
65
+ kind: "page",
66
+ label,
67
+ accessGroup: "default",
68
+ lifecycle: { version: 1, status: "active", introducedAt: "initial" },
69
+ ...options
70
+ };
64
71
  }
65
72
  function action(label, method, options = {}) {
66
- return { kind: "action", label, method, accessGroup: "default", ...options };
73
+ return {
74
+ kind: "action",
75
+ label,
76
+ method,
77
+ accessGroup: "default",
78
+ lifecycle: { version: 1, status: "active", introducedAt: "initial" },
79
+ ...options
80
+ };
67
81
  }
68
82
  function defineRoutes(routes) {
69
83
  for (const [key, route] of Object.entries(routes)) {
84
+ const lifecycle = route.lifecycle;
85
+ if (!Number.isSafeInteger(lifecycle.version) || lifecycle.version < 1) {
86
+ throw new AccessError("ROUTE_VERSION_INVALID", `"${key}": route version must be a positive integer.`);
87
+ }
88
+ const validTimestamp = (value) => Number.isFinite(Date.parse(value));
89
+ if (lifecycle.introducedAt !== "initial" && !validTimestamp(lifecycle.introducedAt)) {
90
+ throw new AccessError("ROUTE_LIFECYCLE_INVALID", `"${key}": introducedAt must be an ISO timestamp or initial.`);
91
+ }
92
+ if (lifecycle.status === "deprecated" && (!validTimestamp(lifecycle.deprecatedAt) || !validTimestamp(lifecycle.expiresAt) || Date.parse(lifecycle.deprecatedAt) > Date.parse(lifecycle.expiresAt) || lifecycle.replacement === key)) {
93
+ throw new AccessError("ROUTE_LIFECYCLE_INVALID", `"${key}": deprecated route lifecycle is invalid.`);
94
+ }
95
+ if (lifecycle.status === "retired" && (!validTimestamp(lifecycle.retiredAt) || lifecycle.replacement === key)) {
96
+ throw new AccessError("ROUTE_LIFECYCLE_INVALID", `"${key}": retired route lifecycle is invalid.`);
97
+ }
70
98
  if (!/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/.test(route.accessGroup)) {
71
99
  throw new AccessError("ROUTE_ACCESS_INVALID", `"${key}": accessGroup must be a bounded name.`);
72
100
  }
@@ -224,6 +252,10 @@ function defineAccessControl(config) {
224
252
  const route = config.routes[key];
225
253
  if (!route)
226
254
  return false;
255
+ if (route.lifecycle?.status === "retired")
256
+ return false;
257
+ if (route.lifecycle?.status === "deprecated" && Date.parse(context?.now ?? new Date().toISOString()) >= Date.parse(route.lifecycle.expiresAt))
258
+ return false;
227
259
  if (route.feature && !features.includes(route.feature))
228
260
  return false;
229
261
  if (context?.stage && route.stages && !route.stages.includes(context.stage))
@@ -275,7 +307,7 @@ function impactOfDisabling(access, enabledAfter) {
275
307
  }
276
308
  return broken;
277
309
  }
278
- var VERSION = "0.1.13";
310
+ var VERSION = "0.1.15";
279
311
 
280
312
  // src/testing.ts
281
313
  function nameOf(policies, route) {
@@ -0,0 +1,177 @@
1
+ import { type Infer } from './schema';
2
+ export declare const VaultDomainSchema: import("./schema").ContractSchema<"service" | "platform-authority" | "deployment">;
3
+ export type VaultDomain = Infer<typeof VaultDomainSchema>;
4
+ export declare const VaultEntryScopeSchema: import("./schema").ContractSchema<({
5
+ kind: "account";
6
+ } & {}) | ({
7
+ kind: "project";
8
+ projectKey: string;
9
+ } & {}) | ({
10
+ kind: "deployment";
11
+ projectKey: string;
12
+ deploymentKey: string;
13
+ } & {})>;
14
+ export type VaultEntryScope = Infer<typeof VaultEntryScopeSchema>;
15
+ export declare const VaultAccessTargetSchema: import("./schema").ContractSchema<{
16
+ projectKey: string;
17
+ } & {
18
+ deploymentKey?: string | null | undefined;
19
+ }>;
20
+ export type VaultAccessTarget = Infer<typeof VaultAccessTargetSchema>;
21
+ export declare const DeploymentCredentialPurposeSchema: import("./schema").ContractSchema<"deployment-infrastructure" | "runtime-secret">;
22
+ export type DeploymentCredentialPurpose = Infer<typeof DeploymentCredentialPurposeSchema>;
23
+ export declare const DeploymentCredentialRequirementSchema: import("./schema").ContractSchema<{
24
+ alias: string;
25
+ purpose: "deployment-infrastructure" | "runtime-secret";
26
+ defaultEntryKey: string;
27
+ } & {
28
+ schema?: string | undefined;
29
+ }>;
30
+ export type DeploymentCredentialRequirement = Infer<typeof DeploymentCredentialRequirementSchema>;
31
+ /** Exact opaque deployment binding. It contains no secret value. */
32
+ export declare const DeploymentVaultBindingSchema: import("./schema").ContractSchema<{
33
+ schema: string;
34
+ projectKey: string;
35
+ deploymentKey: string;
36
+ alias: string;
37
+ purpose: "deployment-infrastructure" | "runtime-secret";
38
+ vaultEntryRef: string;
39
+ environmentKey: string;
40
+ entryKey: string;
41
+ } & {}>;
42
+ export type DeploymentVaultBinding = Infer<typeof DeploymentVaultBindingSchema>;
43
+ export declare const DeploymentVaultBindingsSchema: import("./schema").ContractSchema<Record<string, {
44
+ schema: string;
45
+ projectKey: string;
46
+ deploymentKey: string;
47
+ alias: string;
48
+ purpose: "deployment-infrastructure" | "runtime-secret";
49
+ vaultEntryRef: string;
50
+ environmentKey: string;
51
+ entryKey: string;
52
+ } & {}>>;
53
+ export type DeploymentVaultBindings = Infer<typeof DeploymentVaultBindingsSchema>;
54
+ export declare const DeploymentVaultEntryTypeSchema: import("./schema").ContractSchema<"text" | "secret" | "json">;
55
+ export type DeploymentVaultEntryType = Infer<typeof DeploymentVaultEntryTypeSchema>;
56
+ /**
57
+ * A checked-in schema accepts its declared structured value. When the plan has
58
+ * no dedicated form schema, the manual variants remain deliberately small and
59
+ * map to the built-in Text/Secret catalogue.
60
+ */
61
+ export declare const DeploymentVaultEntryInputSchema: import("./schema").ContractSchema<({
62
+ projectKey: string;
63
+ deploymentKey: string;
64
+ environmentKey: string;
65
+ entryKey: string;
66
+ } & {
67
+ schema?: string | undefined;
68
+ description?: string | undefined;
69
+ } & {
70
+ value: string;
71
+ entryType: "text";
72
+ } & {}) | ({
73
+ projectKey: string;
74
+ deploymentKey: string;
75
+ environmentKey: string;
76
+ entryKey: string;
77
+ } & {
78
+ schema?: string | undefined;
79
+ description?: string | undefined;
80
+ } & {
81
+ value: string;
82
+ entryType: "secret";
83
+ } & {}) | ({
84
+ projectKey: string;
85
+ deploymentKey: string;
86
+ environmentKey: string;
87
+ entryKey: string;
88
+ } & {
89
+ schema?: string | undefined;
90
+ description?: string | undefined;
91
+ } & {
92
+ value: string;
93
+ entryType: "json";
94
+ } & {}) | ({
95
+ projectKey: string;
96
+ deploymentKey: string;
97
+ environmentKey: string;
98
+ entryKey: string;
99
+ } & {
100
+ schema?: string | undefined;
101
+ description?: string | undefined;
102
+ } & {
103
+ value: unknown;
104
+ schema: string;
105
+ } & {})>;
106
+ export type DeploymentVaultEntryInput = Infer<typeof DeploymentVaultEntryInputSchema>;
107
+ export declare const PipelineVaultBindRequestSchema: import("./schema").ContractSchema<{
108
+ alias: string;
109
+ environmentKey: string;
110
+ entryKey: string;
111
+ pipelineKey: string;
112
+ } & {}>;
113
+ export type PipelineVaultBindRequest = Infer<typeof PipelineVaultBindRequestSchema>;
114
+ export declare const PipelineVaultUnbindRequestSchema: import("./schema").ContractSchema<{
115
+ alias: string;
116
+ pipelineKey: string;
117
+ } & {}>;
118
+ export type PipelineVaultUnbindRequest = Infer<typeof PipelineVaultUnbindRequestSchema>;
119
+ export declare const DeploymentVaultCreateAndBindRequestSchema: import("./schema").ContractSchema<{
120
+ entry: ({
121
+ projectKey: string;
122
+ deploymentKey: string;
123
+ environmentKey: string;
124
+ entryKey: string;
125
+ } & {
126
+ schema?: string | undefined;
127
+ description?: string | undefined;
128
+ } & {
129
+ value: string;
130
+ entryType: "text";
131
+ } & {}) | ({
132
+ projectKey: string;
133
+ deploymentKey: string;
134
+ environmentKey: string;
135
+ entryKey: string;
136
+ } & {
137
+ schema?: string | undefined;
138
+ description?: string | undefined;
139
+ } & {
140
+ value: string;
141
+ entryType: "secret";
142
+ } & {}) | ({
143
+ projectKey: string;
144
+ deploymentKey: string;
145
+ environmentKey: string;
146
+ entryKey: string;
147
+ } & {
148
+ schema?: string | undefined;
149
+ description?: string | undefined;
150
+ } & {
151
+ value: string;
152
+ entryType: "json";
153
+ } & {}) | ({
154
+ projectKey: string;
155
+ deploymentKey: string;
156
+ environmentKey: string;
157
+ entryKey: string;
158
+ } & {
159
+ schema?: string | undefined;
160
+ description?: string | undefined;
161
+ } & {
162
+ value: unknown;
163
+ schema: string;
164
+ } & {});
165
+ alias: string;
166
+ pipelineKey: string;
167
+ } & {}>;
168
+ export type DeploymentVaultCreateAndBindRequest = Infer<typeof DeploymentVaultCreateAndBindRequestSchema>;
169
+ export declare function validVaultEntryScope(value: unknown): value is VaultEntryScope;
170
+ /** Human selection may bind a reusable service entry explicitly. */
171
+ export declare function vaultScopeAllows(scope: VaultEntryScope, target: VaultAccessTarget): boolean;
172
+ /** Agent access never inherits account/project wildcard access. */
173
+ export declare function deploymentBindingAllows(binding: DeploymentVaultBinding, target: {
174
+ projectKey: string;
175
+ deploymentKey: string;
176
+ alias: string;
177
+ }): boolean;