@habitat-ai/service 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +16 -0
- package/dist/client.js +16 -0
- package/dist/service/base.d.ts +28 -0
- package/dist/service/base.js +1 -0
- package/dist/service/contract.d.ts +10 -0
- package/dist/service/contract.js +5 -0
- package/dist/service/impl.d.ts +508 -0
- package/dist/service/impl.js +7 -0
- package/dist/service/modules/catalog/contract/catalog.d.ts +252 -0
- package/dist/service/modules/catalog/contract/catalog.js +13 -0
- package/dist/service/modules/catalog/contract/index.d.ts +3 -0
- package/dist/service/modules/catalog/contract/index.js +3 -0
- package/dist/service/modules/catalog/model/dto/catalog.d.ts +276 -0
- package/dist/service/modules/catalog/model/dto/catalog.js +380 -0
- package/dist/service/modules/catalog/model/dto/check.d.ts +104 -0
- package/dist/service/modules/catalog/model/dto/check.js +305 -0
- package/dist/service/modules/catalog/model/dto/structure.d.ts +23 -0
- package/dist/service/modules/catalog/model/dto/structure.js +93 -0
- package/dist/service/modules/catalog/model/policy/catalog.d.ts +109 -0
- package/dist/service/modules/catalog/model/policy/catalog.js +607 -0
- package/dist/service/modules/catalog/model/policy/check.d.ts +57 -0
- package/dist/service/modules/catalog/model/policy/check.js +207 -0
- package/dist/service/modules/catalog/model/policy/structure.d.ts +64 -0
- package/dist/service/modules/catalog/model/policy/structure.js +249 -0
- package/dist/service/modules/catalog/module.d.ts +521 -0
- package/dist/service/modules/catalog/module.js +12 -0
- package/dist/service/modules/catalog/router/catalog.router.d.ts +266 -0
- package/dist/service/modules/catalog/router/catalog.router.js +659 -0
- package/dist/service/modules/catalog/router.d.ts +265 -0
- package/dist/service/modules/catalog/router.js +3 -0
- package/dist/service/router.d.ts +267 -0
- package/dist/service/router.js +4 -0
- package/package.json +49 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { RuleEvaluationFailureReasonSchema, RuleEvaluationPositionSchema, } from "@habitat-ai/resource-rule-evaluation";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
import { CatalogIssueSchema } from "./catalog.js";
|
|
4
|
+
const SelectorValueSchema = Type.String({
|
|
5
|
+
minLength: 1,
|
|
6
|
+
maxLength: 250,
|
|
7
|
+
description: "Non-empty selector value interpreted against resolved applications.",
|
|
8
|
+
});
|
|
9
|
+
const CheckSelectorsSchema = Type.Object({
|
|
10
|
+
owner: Type.Optional(Type.String({
|
|
11
|
+
minLength: 1,
|
|
12
|
+
maxLength: 250,
|
|
13
|
+
description: "Repository project identity whose applications enter the check.",
|
|
14
|
+
})),
|
|
15
|
+
instance: Type.Optional(Type.String({
|
|
16
|
+
minLength: 1,
|
|
17
|
+
maxLength: 250,
|
|
18
|
+
description: "Exact resolved instance identity whose applications enter the check.",
|
|
19
|
+
})),
|
|
20
|
+
rule: Type.Optional(Type.String({
|
|
21
|
+
minLength: 1,
|
|
22
|
+
maxLength: 200,
|
|
23
|
+
description: "Single rule identity whose applications enter the check.",
|
|
24
|
+
})),
|
|
25
|
+
rules: Type.Optional(Type.Array(SelectorValueSchema, {
|
|
26
|
+
minItems: 1,
|
|
27
|
+
uniqueItems: true,
|
|
28
|
+
description: "Rule identities whose applications enter the check.",
|
|
29
|
+
})),
|
|
30
|
+
runner: Type.Optional(Type.String({
|
|
31
|
+
minLength: 1,
|
|
32
|
+
maxLength: 100,
|
|
33
|
+
description: "Runner identity whose applications enter the check.",
|
|
34
|
+
})),
|
|
35
|
+
}, {
|
|
36
|
+
additionalProperties: false,
|
|
37
|
+
description: "Optional intersection of resolved-application selectors.",
|
|
38
|
+
});
|
|
39
|
+
/** Closed request for checking the currently resolved Habitat catalog. */
|
|
40
|
+
export const CheckCatalogInputSchema = Type.Object({
|
|
41
|
+
selectors: Type.Optional(CheckSelectorsSchema),
|
|
42
|
+
}, {
|
|
43
|
+
additionalProperties: false,
|
|
44
|
+
description: "Habitat catalog check request.",
|
|
45
|
+
});
|
|
46
|
+
const CheckSelectionIssueCodeSchema = Type.Union([
|
|
47
|
+
Type.Literal("selector-empty"),
|
|
48
|
+
Type.Literal("selector-unknown"),
|
|
49
|
+
Type.Literal("selector-wrong-namespace"),
|
|
50
|
+
Type.Literal("runner-unsupported"),
|
|
51
|
+
], {
|
|
52
|
+
description: "Stable semantic reason a requested application selection was refused.",
|
|
53
|
+
});
|
|
54
|
+
const CheckSelectionIssueSchema = Type.Object({
|
|
55
|
+
code: CheckSelectionIssueCodeSchema,
|
|
56
|
+
selector: Type.String({
|
|
57
|
+
minLength: 1,
|
|
58
|
+
maxLength: 500,
|
|
59
|
+
description: "Selector or application identity responsible for the refusal.",
|
|
60
|
+
}),
|
|
61
|
+
message: Type.String({
|
|
62
|
+
minLength: 1,
|
|
63
|
+
maxLength: 8_192,
|
|
64
|
+
description: "Bounded refusal detail.",
|
|
65
|
+
}),
|
|
66
|
+
}, {
|
|
67
|
+
additionalProperties: false,
|
|
68
|
+
description: "One expected application-selection refusal.",
|
|
69
|
+
});
|
|
70
|
+
const GritCheckFindingSchema = Type.Object({
|
|
71
|
+
path: Type.String({
|
|
72
|
+
minLength: 1,
|
|
73
|
+
maxLength: 4_096,
|
|
74
|
+
description: "Normalized repository-relative source path.",
|
|
75
|
+
}),
|
|
76
|
+
start: RuleEvaluationPositionSchema,
|
|
77
|
+
end: RuleEvaluationPositionSchema,
|
|
78
|
+
message: Type.Union([Type.String(), Type.Null()], {
|
|
79
|
+
description: "Evaluator-authored diagnostic message when one was produced.",
|
|
80
|
+
}),
|
|
81
|
+
severity: Type.Union([Type.Literal("error"), Type.Literal("advisory")], {
|
|
82
|
+
description: "Service-owned severity derived from the application lane.",
|
|
83
|
+
}),
|
|
84
|
+
baselined: Type.Literal(false, {
|
|
85
|
+
description: "Version-three findings are not admitted through the predecessor baseline model.",
|
|
86
|
+
}),
|
|
87
|
+
}, {
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
description: "One mechanically observed finding with Habitat semantics.",
|
|
90
|
+
});
|
|
91
|
+
const CheckApplicationStatusSchema = Type.Union([
|
|
92
|
+
Type.Literal("pass"),
|
|
93
|
+
Type.Literal("fail"),
|
|
94
|
+
Type.Literal("advisory-findings"),
|
|
95
|
+
Type.Literal("error"),
|
|
96
|
+
], {
|
|
97
|
+
description: "Semantic terminal status for one resolved application.",
|
|
98
|
+
});
|
|
99
|
+
const GritCheckApplicationDispositionSchema = Type.Union([
|
|
100
|
+
Type.Object({
|
|
101
|
+
kind: Type.Literal("evaluated", {
|
|
102
|
+
description: "The application completed mechanical evaluation.",
|
|
103
|
+
}),
|
|
104
|
+
}, {
|
|
105
|
+
additionalProperties: false,
|
|
106
|
+
description: "Completed mechanical evaluation disposition.",
|
|
107
|
+
}),
|
|
108
|
+
Type.Object({
|
|
109
|
+
kind: Type.Literal("failed", {
|
|
110
|
+
description: "The application could not produce trusted findings.",
|
|
111
|
+
}),
|
|
112
|
+
reason: Type.Union([
|
|
113
|
+
RuleEvaluationFailureReasonSchema,
|
|
114
|
+
Type.Literal("PatternReadFailed"),
|
|
115
|
+
Type.Literal("PatternInvalid"),
|
|
116
|
+
Type.Literal("FindingPathInvalid"),
|
|
117
|
+
], {
|
|
118
|
+
description: "Stable operational failure reason.",
|
|
119
|
+
}),
|
|
120
|
+
detail: Type.String({
|
|
121
|
+
minLength: 1,
|
|
122
|
+
maxLength: 4_096,
|
|
123
|
+
description: "Bounded operational failure detail.",
|
|
124
|
+
}),
|
|
125
|
+
}, {
|
|
126
|
+
additionalProperties: false,
|
|
127
|
+
description: "Failed application evaluation disposition.",
|
|
128
|
+
}),
|
|
129
|
+
], {
|
|
130
|
+
description: "Mechanical disposition underlying one semantic application status.",
|
|
131
|
+
});
|
|
132
|
+
const GritCheckApplicationReportSchema = Type.Object({
|
|
133
|
+
ownerProject: Type.String({
|
|
134
|
+
minLength: 1,
|
|
135
|
+
maxLength: 250,
|
|
136
|
+
description: "Repository project that owns the resolved application.",
|
|
137
|
+
}),
|
|
138
|
+
instanceId: Type.String({
|
|
139
|
+
minLength: 1,
|
|
140
|
+
maxLength: 250,
|
|
141
|
+
description: "Repository-unique instance identity.",
|
|
142
|
+
}),
|
|
143
|
+
ruleId: Type.String({
|
|
144
|
+
minLength: 1,
|
|
145
|
+
maxLength: 200,
|
|
146
|
+
description: "Resolved rule identity.",
|
|
147
|
+
}),
|
|
148
|
+
runner: Type.Literal("grit", {
|
|
149
|
+
description: "Mechanical runner used by this check operation.",
|
|
150
|
+
}),
|
|
151
|
+
lane: Type.Union([Type.Literal("enforced"), Type.Literal("advisory")], {
|
|
152
|
+
description: "Application policy lane.",
|
|
153
|
+
}),
|
|
154
|
+
locked: Type.Literal(false, {
|
|
155
|
+
description: "Version-three applications do not inherit predecessor baseline locking.",
|
|
156
|
+
}),
|
|
157
|
+
status: CheckApplicationStatusSchema,
|
|
158
|
+
message: Type.String({
|
|
159
|
+
minLength: 1,
|
|
160
|
+
maxLength: 8_192,
|
|
161
|
+
description: "Rule-authored finding message.",
|
|
162
|
+
}),
|
|
163
|
+
remediate: Type.Union([Type.String({ maxLength: 16_384 }), Type.Null()], {
|
|
164
|
+
description: "Rule-authored remediation when supplied.",
|
|
165
|
+
}),
|
|
166
|
+
disposition: GritCheckApplicationDispositionSchema,
|
|
167
|
+
findings: Type.Array(GritCheckFindingSchema, {
|
|
168
|
+
description: "Deterministically ordered findings for this application.",
|
|
169
|
+
}),
|
|
170
|
+
}, {
|
|
171
|
+
additionalProperties: false,
|
|
172
|
+
description: "One resolved application check report.",
|
|
173
|
+
});
|
|
174
|
+
const StructureFindingCodeSchema = Type.Union([
|
|
175
|
+
Type.Literal("root-missing"),
|
|
176
|
+
Type.Literal("wrong-root-kind"),
|
|
177
|
+
Type.Literal("missing-required-child"),
|
|
178
|
+
Type.Literal("forbidden-child"),
|
|
179
|
+
Type.Literal("unexpected-child"),
|
|
180
|
+
], { description: "Stable native Habitat structure diagnostic classification." });
|
|
181
|
+
const StructureCheckFindingSchema = Type.Object({
|
|
182
|
+
path: Type.String({
|
|
183
|
+
minLength: 1,
|
|
184
|
+
maxLength: 4_096,
|
|
185
|
+
description: "Normalized repository-relative structure path.",
|
|
186
|
+
}),
|
|
187
|
+
code: StructureFindingCodeSchema,
|
|
188
|
+
message: Type.String({
|
|
189
|
+
minLength: 1,
|
|
190
|
+
maxLength: 8_192,
|
|
191
|
+
description: "Deterministic Habitat-authored structure diagnostic.",
|
|
192
|
+
}),
|
|
193
|
+
severity: Type.Union([Type.Literal("error"), Type.Literal("advisory")], {
|
|
194
|
+
description: "Service-owned severity derived from the application lane.",
|
|
195
|
+
}),
|
|
196
|
+
baselined: Type.Literal(false, {
|
|
197
|
+
description: "Version-three findings do not inherit predecessor baselines.",
|
|
198
|
+
}),
|
|
199
|
+
}, { additionalProperties: false, description: "One path-only native structure finding." });
|
|
200
|
+
const StructureCheckApplicationDispositionSchema = Type.Union([
|
|
201
|
+
Type.Object({
|
|
202
|
+
kind: Type.Literal("evaluated", {
|
|
203
|
+
description: "Native structure evaluation completed.",
|
|
204
|
+
}),
|
|
205
|
+
}, { additionalProperties: false, description: "Completed native structure evaluation." }),
|
|
206
|
+
Type.Object({
|
|
207
|
+
kind: Type.Literal("failed", {
|
|
208
|
+
description: "Native structure evaluation failed operationally.",
|
|
209
|
+
}),
|
|
210
|
+
reason: Type.Union([
|
|
211
|
+
Type.Literal("StructureReadFailed"),
|
|
212
|
+
Type.Literal("StructureInvalid"),
|
|
213
|
+
Type.Literal("InventoryFailed"),
|
|
214
|
+
Type.Literal("StructureObservationFailed"),
|
|
215
|
+
], { description: "Stable native structure operational failure reason." }),
|
|
216
|
+
detail: Type.String({
|
|
217
|
+
minLength: 1,
|
|
218
|
+
maxLength: 4_096,
|
|
219
|
+
description: "Bounded native structure failure detail.",
|
|
220
|
+
}),
|
|
221
|
+
}, { additionalProperties: false, description: "Failed native structure evaluation." }),
|
|
222
|
+
], { description: "Native structure evaluation disposition." });
|
|
223
|
+
const StructureCheckApplicationReportSchema = Type.Object({
|
|
224
|
+
ownerProject: Type.String({
|
|
225
|
+
minLength: 1,
|
|
226
|
+
maxLength: 250,
|
|
227
|
+
description: "Repository project that owns this structure application.",
|
|
228
|
+
}),
|
|
229
|
+
instanceId: Type.String({
|
|
230
|
+
minLength: 1,
|
|
231
|
+
maxLength: 250,
|
|
232
|
+
description: "Resolved instance evaluated by this structure application.",
|
|
233
|
+
}),
|
|
234
|
+
ruleId: Type.String({
|
|
235
|
+
minLength: 1,
|
|
236
|
+
maxLength: 200,
|
|
237
|
+
description: "Native structure rule evaluated for this instance.",
|
|
238
|
+
}),
|
|
239
|
+
runner: Type.Literal("habitat", {
|
|
240
|
+
description: "Native Habitat runner used by this application.",
|
|
241
|
+
}),
|
|
242
|
+
lane: Type.Union([Type.Literal("enforced"), Type.Literal("advisory")], {
|
|
243
|
+
description: "Policy lane that determines finding severity and completion status.",
|
|
244
|
+
}),
|
|
245
|
+
locked: Type.Literal(false, {
|
|
246
|
+
description: "Native structure reports do not expose Grit lock semantics.",
|
|
247
|
+
}),
|
|
248
|
+
status: CheckApplicationStatusSchema,
|
|
249
|
+
message: Type.String({
|
|
250
|
+
minLength: 1,
|
|
251
|
+
maxLength: 8_192,
|
|
252
|
+
description: "Catalog-authored human guidance for this structure rule.",
|
|
253
|
+
}),
|
|
254
|
+
remediate: Type.Union([Type.String({ maxLength: 16_384 }), Type.Null()], {
|
|
255
|
+
description: "Optional catalog-authored remediation guidance.",
|
|
256
|
+
}),
|
|
257
|
+
disposition: StructureCheckApplicationDispositionSchema,
|
|
258
|
+
findings: Type.Array(StructureCheckFindingSchema, {
|
|
259
|
+
description: "Deterministically ordered path-only structure findings.",
|
|
260
|
+
}),
|
|
261
|
+
}, { additionalProperties: false, description: "One native Habitat structure report." });
|
|
262
|
+
const CheckApplicationReportSchema = Type.Union([GritCheckApplicationReportSchema, StructureCheckApplicationReportSchema], { description: "Runner-discriminated application check report." });
|
|
263
|
+
/** Closed total result for one current-catalog check. */
|
|
264
|
+
export const CheckCatalogResultSchema = Type.Union([
|
|
265
|
+
Type.Object({
|
|
266
|
+
_tag: Type.Literal("CatalogRejected", {
|
|
267
|
+
description: "Catalog admission failed before application selection.",
|
|
268
|
+
}),
|
|
269
|
+
issues: Type.Array(CatalogIssueSchema, {
|
|
270
|
+
minItems: 1,
|
|
271
|
+
description: "Catalog issues that prevented checking.",
|
|
272
|
+
}),
|
|
273
|
+
}, {
|
|
274
|
+
additionalProperties: false,
|
|
275
|
+
description: "Catalog-stage check refusal.",
|
|
276
|
+
}),
|
|
277
|
+
Type.Object({
|
|
278
|
+
_tag: Type.Literal("SelectionRejected", {
|
|
279
|
+
description: "Application selection failed before mechanical evaluation.",
|
|
280
|
+
}),
|
|
281
|
+
issues: Type.Array(CheckSelectionIssueSchema, {
|
|
282
|
+
minItems: 1,
|
|
283
|
+
description: "Selection issues that prevented checking.",
|
|
284
|
+
}),
|
|
285
|
+
}, {
|
|
286
|
+
additionalProperties: false,
|
|
287
|
+
description: "Selection-stage check refusal.",
|
|
288
|
+
}),
|
|
289
|
+
Type.Object({
|
|
290
|
+
_tag: Type.Literal("Completed", {
|
|
291
|
+
description: "All selected applications reached a semantic terminal status.",
|
|
292
|
+
}),
|
|
293
|
+
ok: Type.Boolean({
|
|
294
|
+
description: "Whether no enforced finding or operational error occurred.",
|
|
295
|
+
}),
|
|
296
|
+
applications: Type.Array(CheckApplicationReportSchema, {
|
|
297
|
+
description: "Application reports in stable rule and instance order.",
|
|
298
|
+
}),
|
|
299
|
+
}, {
|
|
300
|
+
additionalProperties: false,
|
|
301
|
+
description: "Completed Habitat catalog check.",
|
|
302
|
+
}),
|
|
303
|
+
], {
|
|
304
|
+
description: "Catalog refusal, selection refusal, or completed check outcome.",
|
|
305
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import picomatch from "picomatch";
|
|
2
|
+
import { type Static, Type } from "typebox";
|
|
3
|
+
/** Glob options shared by schema admission and native structure evaluation. */
|
|
4
|
+
export declare const STRUCTURE_PICOMATCH_OPTIONS: Readonly<picomatch.PicomatchOptions>;
|
|
5
|
+
/** Sole structural authority for one version-two Habitat structure document. */
|
|
6
|
+
export declare const StructureDocumentSchema: Type.TRefine<Type.TObject<{
|
|
7
|
+
schemaVersion: Type.TLiteral<2>;
|
|
8
|
+
scopes: Type.TArray<Type.TObject<{
|
|
9
|
+
name: Type.TString;
|
|
10
|
+
rootRole: Type.TString;
|
|
11
|
+
relativePath: Type.TRefine<Type.TString>;
|
|
12
|
+
kind: Type.TUnion<[Type.TLiteral<"directory">, Type.TLiteral<"file">]>;
|
|
13
|
+
mode: Type.TUnion<[Type.TLiteral<"open">, Type.TLiteral<"closed">]>;
|
|
14
|
+
allowEmpty: Type.TOptional<Type.TBoolean>;
|
|
15
|
+
required: Type.TOptional<Type.TArray<Type.TRefine<Type.TString>>>;
|
|
16
|
+
allowed: Type.TOptional<Type.TArray<Type.TRefine<Type.TString>>>;
|
|
17
|
+
forbidden: Type.TOptional<Type.TArray<Type.TRefine<Type.TString>>>;
|
|
18
|
+
}>>;
|
|
19
|
+
}>>;
|
|
20
|
+
/** Schema-admitted version-two Habitat structure document. */
|
|
21
|
+
export type StructureDocument = Static<typeof StructureDocumentSchema>;
|
|
22
|
+
/** One schema-admitted structure scope. */
|
|
23
|
+
export type StructureScope = StructureDocument["scopes"][number];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import picomatch from "picomatch";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
/** Glob options shared by schema admission and native structure evaluation. */
|
|
4
|
+
export const STRUCTURE_PICOMATCH_OPTIONS = Object.freeze({
|
|
5
|
+
contains: false,
|
|
6
|
+
dot: true,
|
|
7
|
+
strictBrackets: true,
|
|
8
|
+
});
|
|
9
|
+
const RootRoleSchema = Type.String({
|
|
10
|
+
minLength: 1,
|
|
11
|
+
maxLength: 200,
|
|
12
|
+
pattern: "^[a-z0-9][a-z0-9_-]*$",
|
|
13
|
+
description: "Blueprint root role used as the base for one structure scope.",
|
|
14
|
+
});
|
|
15
|
+
const RootRelativePatternSchema = Type.Refine(Type.String({
|
|
16
|
+
minLength: 1,
|
|
17
|
+
maxLength: 4_096,
|
|
18
|
+
description: "Safe root-relative path or glob selecting structure roots.",
|
|
19
|
+
}), isSafeRootRelativePattern, () => "Expected a safe, valid root-relative path or glob");
|
|
20
|
+
const DirectChildPatternSchema = Type.Refine(Type.String({
|
|
21
|
+
minLength: 1,
|
|
22
|
+
maxLength: 1_024,
|
|
23
|
+
description: "Glob matched against one direct child name.",
|
|
24
|
+
}), isSafeDirectChildPattern, () => "Expected a safe, valid direct-child glob");
|
|
25
|
+
const StructureScopeSchema = Type.Object({
|
|
26
|
+
name: Type.String({
|
|
27
|
+
minLength: 1,
|
|
28
|
+
maxLength: 200,
|
|
29
|
+
description: "Stable identity for one structure scope.",
|
|
30
|
+
}),
|
|
31
|
+
rootRole: RootRoleSchema,
|
|
32
|
+
relativePath: RootRelativePatternSchema,
|
|
33
|
+
kind: Type.Union([Type.Literal("directory"), Type.Literal("file")], {
|
|
34
|
+
description: "Expected kind for every matched scope root.",
|
|
35
|
+
}),
|
|
36
|
+
mode: Type.Union([Type.Literal("open"), Type.Literal("closed")], {
|
|
37
|
+
description: "Whether unmatched direct children are admitted.",
|
|
38
|
+
}),
|
|
39
|
+
allowEmpty: Type.Optional(Type.Boolean({ description: "Whether a scope may match no visible roots." })),
|
|
40
|
+
required: Type.Optional(Type.Array(DirectChildPatternSchema, {
|
|
41
|
+
uniqueItems: true,
|
|
42
|
+
description: "Unique direct-child globs that must each match at least one child.",
|
|
43
|
+
})),
|
|
44
|
+
allowed: Type.Optional(Type.Array(DirectChildPatternSchema, {
|
|
45
|
+
uniqueItems: true,
|
|
46
|
+
description: "Unique direct-child globs admitted by a closed scope.",
|
|
47
|
+
})),
|
|
48
|
+
forbidden: Type.Optional(Type.Array(DirectChildPatternSchema, {
|
|
49
|
+
uniqueItems: true,
|
|
50
|
+
description: "Unique direct-child globs rejected in every scope mode.",
|
|
51
|
+
})),
|
|
52
|
+
}, { additionalProperties: false, description: "One closed Habitat structure scope." });
|
|
53
|
+
const StructureDocumentShapeSchema = Type.Object({
|
|
54
|
+
schemaVersion: Type.Literal(2, { description: "Structure document schema version." }),
|
|
55
|
+
scopes: Type.Array(StructureScopeSchema, {
|
|
56
|
+
minItems: 1,
|
|
57
|
+
description: "Structure scopes evaluated in declared order.",
|
|
58
|
+
}),
|
|
59
|
+
}, { additionalProperties: false, description: "Closed Habitat structure document." });
|
|
60
|
+
/** Sole structural authority for one version-two Habitat structure document. */
|
|
61
|
+
export const StructureDocumentSchema = Type.Refine(StructureDocumentShapeSchema, hasUniqueScopeNames, () => "Expected unique structure scope names");
|
|
62
|
+
function hasUniqueScopeNames(document) {
|
|
63
|
+
return new Set(document.scopes.map((scope) => scope.name)).size === document.scopes.length;
|
|
64
|
+
}
|
|
65
|
+
function isSafeRootRelativePattern(value) {
|
|
66
|
+
if (!isValidGlob(value))
|
|
67
|
+
return false;
|
|
68
|
+
if (value === ".")
|
|
69
|
+
return true;
|
|
70
|
+
return (!value.startsWith("/") &&
|
|
71
|
+
!value.endsWith("/") &&
|
|
72
|
+
!value.includes("\\") &&
|
|
73
|
+
!/^[A-Za-z]:\//u.test(value) &&
|
|
74
|
+
!/[\u0000-\u001f\u007f]/u.test(value) &&
|
|
75
|
+
value.split("/").every((segment) => segment !== "" && segment !== "." && segment !== ".."));
|
|
76
|
+
}
|
|
77
|
+
function isSafeDirectChildPattern(value) {
|
|
78
|
+
return (isValidGlob(value) &&
|
|
79
|
+
value !== "." &&
|
|
80
|
+
value !== ".." &&
|
|
81
|
+
!value.includes("/") &&
|
|
82
|
+
!value.includes("\\") &&
|
|
83
|
+
!/[\u0000-\u001f\u007f]/u.test(value));
|
|
84
|
+
}
|
|
85
|
+
function isValidGlob(value) {
|
|
86
|
+
try {
|
|
87
|
+
picomatch(value, STRUCTURE_PICOMATCH_OPTIONS);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { Path } from "effect";
|
|
2
|
+
import { type BlueprintDefinition, type CatalogIssue, type CompatibilityIndex, type CompatibilityRuleSource, type HabitatInstanceManifest, type PolicyPackManifest, type PolicyPackPackageJson, type ResolveCatalogResult } from "../dto/catalog.js";
|
|
3
|
+
/** One schema-admitted local blueprint source. */
|
|
4
|
+
export type BlueprintSource = {
|
|
5
|
+
readonly definition: BlueprintDefinition;
|
|
6
|
+
readonly relativePath: string;
|
|
7
|
+
};
|
|
8
|
+
/** One admitted selected npm policy-pack envelope. */
|
|
9
|
+
export type PolicyPackSource = {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly version: string;
|
|
12
|
+
readonly protocolVersion: 1;
|
|
13
|
+
readonly blueprints: readonly [];
|
|
14
|
+
};
|
|
15
|
+
/** App-selected absolute package locators interpreted before filesystem I/O. */
|
|
16
|
+
export type PolicyPackSelection = {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly packageJsonPath: string;
|
|
19
|
+
readonly manifestPath: string;
|
|
20
|
+
};
|
|
21
|
+
/** One schema-admitted local instance source. */
|
|
22
|
+
export type InstanceSource = {
|
|
23
|
+
readonly manifest: HabitatInstanceManifest;
|
|
24
|
+
readonly relativePath: string;
|
|
25
|
+
};
|
|
26
|
+
/** One schema-admitted inert compatibility rule source. */
|
|
27
|
+
export type CompatibilityRuleDocument = {
|
|
28
|
+
readonly rule: CompatibilityRuleSource;
|
|
29
|
+
readonly relativePath: string;
|
|
30
|
+
};
|
|
31
|
+
/** Schema-admitted authority documents observed by the resolve handler. */
|
|
32
|
+
export type CatalogDocuments = {
|
|
33
|
+
readonly policyPack: PolicyPackSource;
|
|
34
|
+
readonly blueprints: readonly BlueprintSource[];
|
|
35
|
+
readonly manifests: readonly InstanceSource[];
|
|
36
|
+
readonly compatibilityIndex?: CompatibilityIndex;
|
|
37
|
+
readonly compatibilityRules: readonly CompatibilityRuleDocument[];
|
|
38
|
+
};
|
|
39
|
+
/** Validates the selected policy-pack filesystem locators. */
|
|
40
|
+
export declare function admitPolicyPackSelection(selection: PolicyPackSelection, path: Path.Path): {
|
|
41
|
+
readonly ok: true;
|
|
42
|
+
readonly selection: PolicyPackSelection;
|
|
43
|
+
} | {
|
|
44
|
+
readonly ok: false;
|
|
45
|
+
readonly issues: readonly CatalogIssue[];
|
|
46
|
+
};
|
|
47
|
+
/** Admits selected package.json identity through the existing TypeBox validator pattern. */
|
|
48
|
+
export declare function admitPolicyPackPackageJson(value: unknown, expectedName: string, sourcePath: string): {
|
|
49
|
+
readonly ok: true;
|
|
50
|
+
readonly value: PolicyPackPackageJson;
|
|
51
|
+
} | {
|
|
52
|
+
readonly ok: false;
|
|
53
|
+
readonly issues: readonly CatalogIssue[];
|
|
54
|
+
};
|
|
55
|
+
/** Admits the closed protocol envelope and refuses future member activation explicitly. */
|
|
56
|
+
export declare function admitPolicyPackManifest(value: unknown, sourcePath: string): {
|
|
57
|
+
readonly ok: true;
|
|
58
|
+
readonly value: PolicyPackManifest;
|
|
59
|
+
} | {
|
|
60
|
+
readonly ok: false;
|
|
61
|
+
readonly issues: readonly CatalogIssue[];
|
|
62
|
+
};
|
|
63
|
+
/** Service-observed filesystem facts for one referenced repository path. */
|
|
64
|
+
export type CatalogPathFact = {
|
|
65
|
+
readonly relativePath: string;
|
|
66
|
+
readonly absolutePath: string;
|
|
67
|
+
readonly kind: "directory" | "file" | "missing" | "other";
|
|
68
|
+
readonly realPath?: string;
|
|
69
|
+
readonly detail?: string;
|
|
70
|
+
readonly filesystemError?: boolean;
|
|
71
|
+
};
|
|
72
|
+
/** Admits unknown TOML output as one closed blueprint definition. */
|
|
73
|
+
export declare function admitBlueprintSource(value: unknown, relativePath: string): {
|
|
74
|
+
readonly ok: true;
|
|
75
|
+
readonly source: BlueprintSource;
|
|
76
|
+
} | {
|
|
77
|
+
readonly ok: false;
|
|
78
|
+
readonly issues: readonly CatalogIssue[];
|
|
79
|
+
};
|
|
80
|
+
/** Admits unknown TOML output as one closed instance manifest. */
|
|
81
|
+
export declare function admitInstanceSource(value: unknown, relativePath: string): {
|
|
82
|
+
readonly ok: true;
|
|
83
|
+
readonly source: InstanceSource;
|
|
84
|
+
} | {
|
|
85
|
+
readonly ok: false;
|
|
86
|
+
readonly issues: readonly CatalogIssue[];
|
|
87
|
+
};
|
|
88
|
+
/** Admits unknown JSON output as the closed legacy index. */
|
|
89
|
+
export declare function admitCompatibilityIndex(value: unknown, relativePath: string): {
|
|
90
|
+
readonly ok: true;
|
|
91
|
+
readonly value: CompatibilityIndex;
|
|
92
|
+
} | {
|
|
93
|
+
readonly ok: false;
|
|
94
|
+
readonly issues: readonly CatalogIssue[];
|
|
95
|
+
};
|
|
96
|
+
/** Admits only the inert identity fields required from a legacy rule source. */
|
|
97
|
+
export declare function admitCompatibilityRule(value: unknown, relativePath: string): {
|
|
98
|
+
readonly ok: true;
|
|
99
|
+
readonly source: CompatibilityRuleDocument;
|
|
100
|
+
} | {
|
|
101
|
+
readonly ok: false;
|
|
102
|
+
readonly issues: readonly CatalogIssue[];
|
|
103
|
+
};
|
|
104
|
+
/** Collects filesystem paths that schema-admitted documents require the service to observe. */
|
|
105
|
+
export declare function referencedRepositoryPaths(documents: CatalogDocuments, path: Path.Path): readonly string[];
|
|
106
|
+
/** Resolves admitted documents and observed paths into the closed public catalog union. */
|
|
107
|
+
export declare function resolveCatalog(documents: CatalogDocuments, pathFacts: ReadonlyMap<string, CatalogPathFact>, workspaceRoot: string, workspaceRealRoot: string, path: Path.Path): ResolveCatalogResult;
|
|
108
|
+
/** Constructs a bounded, sorted rejected result for operational failures. */
|
|
109
|
+
export declare function rejected(issues: readonly CatalogIssue[]): ResolveCatalogResult;
|