@delurio/cli 0.1.0 → 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.
@@ -0,0 +1,305 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://unpkg.com/@delurio/cli@0.2.0/schemas/domain.schema.json",
4
+ "title": "delurio domain graph (domain.yaml)",
5
+ "description": "The data and the API of a delurio-graph/0 graph (SPEC.md §5): entities whose fields are JSON Schema (2020-12) with delurio's keywords, actions that are OpenAPI 3.1 operations when they have a route, their refusals, the policies that say who may do what to which data, and the invariants that must always hold.",
6
+ "type": "object",
7
+ "required": ["schema", "kind", "id"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schema": { "$ref": "#/$defs/formatVersion" },
11
+ "kind": { "description": "The kind of graph file. A domain.yaml is `domain`.", "const": "domain" },
12
+ "id": { "$ref": "#/$defs/graphId", "description": "The domain's id; a flow names it with `domain:`.", "examples": ["qauth.authorize", "learning.api"] },
13
+ "title": { "type": "string", "description": "The domain in plain words, for people." },
14
+ "summary": { "type": "string", "description": "What the domain covers, in a few plain sentences." },
15
+ "status": { "$ref": "#/$defs/status" },
16
+ "source": { "$ref": "#/$defs/sourceAnchor" },
17
+ "openapi": { "type": "string", "description": "The OpenAPI document the app already publishes, relative to this file; each action then names its operation by `operationId` instead of copying it." },
18
+ "entities": {
19
+ "type": "object",
20
+ "description": "The data, by entity name. An entity is the JSON Schema `{ type: object, properties: <fields>, required: <required> }`.",
21
+ "additionalProperties": { "$ref": "#/$defs/entity" }
22
+ },
23
+ "policies": {
24
+ "type": "array",
25
+ "description": "Who may do what to which data (delurio's own: no standard says it).",
26
+ "items": { "$ref": "#/$defs/policy" }
27
+ },
28
+ "actions": {
29
+ "type": "object",
30
+ "description": "The API and the steps inside the service, by action name. An action with a `route` is one OpenAPI 3.1 operation whose operationId is its name; one with no route is a step inside the service. An action may be named before it is written (an empty value).",
31
+ "additionalProperties": { "$ref": "#/$defs/action" }
32
+ },
33
+ "invariants": {
34
+ "type": "array",
35
+ "description": "What must always hold (delurio's own: no standard says it).",
36
+ "items": { "$ref": "#/$defs/invariant" }
37
+ }
38
+ },
39
+ "$defs": {
40
+ "formatVersion": {
41
+ "description": "The format and its version. Every graph file starts with it.",
42
+ "const": "delurio-graph/0"
43
+ },
44
+ "status": {
45
+ "description": "`proposed`: written before or apart from the code, nobody has approved it. `captured`: read from existing code (capture mode, every element carries `source`). `approved`: the owner reviewed and accepted it.",
46
+ "enum": ["proposed", "captured", "approved"]
47
+ },
48
+ "graphId": {
49
+ "type": "string",
50
+ "description": "The id of a graph.",
51
+ "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
52
+ },
53
+ "sourceAnchor": {
54
+ "type": "string",
55
+ "description": "A source anchor (SPEC.md §9): `<repo-relative path>:<line>`, or a bare `<path>` for a whole file, naming the code that makes the element true. In capture mode every element carries one.",
56
+ "pattern": "^[^\\s:]+(:[0-9]+)?$",
57
+ "examples": ["src/db/schema.ts:42"]
58
+ },
59
+ "names": {
60
+ "type": "array",
61
+ "description": "Names, each once.",
62
+ "uniqueItems": true,
63
+ "items": { "type": "string" }
64
+ },
65
+ "entity": {
66
+ "type": "object",
67
+ "description": "An entity of the data.",
68
+ "additionalProperties": false,
69
+ "properties": {
70
+ "fields": {
71
+ "type": "object",
72
+ "description": "The entity's fields, by name, each a JSON Schema (2020-12) with delurio's keywords.",
73
+ "additionalProperties": { "$ref": "#/$defs/field" }
74
+ },
75
+ "required": { "$ref": "#/$defs/names", "description": "The fields that must be present." },
76
+ "key": { "$ref": "#/$defs/names", "description": "The fields that identify the entity; `[id]` when left out.", "examples": [["userId", "clientId"]] },
77
+ "lifecycle": {
78
+ "type": "array",
79
+ "description": "The entity's states, as `from -> to: why` sentences. Quote each: an unquoted item that contains `: ` is read as a map.",
80
+ "items": { "type": "string" },
81
+ "examples": [["none -> active: the first sign-in"]]
82
+ },
83
+ "source": { "$ref": "#/$defs/sourceAnchor" }
84
+ }
85
+ },
86
+ "field": {
87
+ "description": "A field: a JSON Schema (2020-12) with delurio's keywords (`references`, `unique`, `sensitivity`). `null` is a type like any other: an optional time is `{ type: [string, \"null\"], format: date-time }`.",
88
+ "$ref": "#/$defs/schemaObject"
89
+ },
90
+ "schema": {
91
+ "description": "A JSON Schema (2020-12) with delurio's keywords, or `true` (any value) or `false` (none).",
92
+ "anyOf": [{ "type": "boolean" }, { "$ref": "#/$defs/schemaObject" }]
93
+ },
94
+ "schemaObject": {
95
+ "type": "object",
96
+ "description": "A JSON Schema (2020-12) with delurio's keywords.",
97
+ "$ref": "#/$defs/keywords",
98
+ "unevaluatedProperties": false
99
+ },
100
+ "schemas": {
101
+ "type": "array",
102
+ "description": "JSON Schemas.",
103
+ "minItems": 1,
104
+ "items": { "$ref": "#/$defs/schema" }
105
+ },
106
+ "schemaMap": {
107
+ "type": "object",
108
+ "description": "JSON Schemas, by name.",
109
+ "additionalProperties": { "$ref": "#/$defs/schema" }
110
+ },
111
+ "typeName": {
112
+ "description": "A JSON type.",
113
+ "enum": ["string", "number", "integer", "boolean", "object", "array", "null"]
114
+ },
115
+ "nonNegative": { "type": "integer", "minimum": 0, "description": "A count, 0 or more." },
116
+ "keywords": {
117
+ "type": "object",
118
+ "description": "The keywords of JSON Schema 2020-12 (core, applicator, unevaluated, validation, meta-data, format and content vocabularies), and the keywords delurio adds, which a JSON Schema validator leaves alone.",
119
+ "properties": {
120
+ "$id": { "type": "string", "description": "JSON Schema: the schema's URI." },
121
+ "$schema": { "type": "string", "description": "JSON Schema: the dialect of the schema." },
122
+ "$ref": { "type": "string", "description": "JSON Schema: a reference to another schema." },
123
+ "$anchor": { "type": "string", "description": "JSON Schema: a plain-name fragment for this schema." },
124
+ "$dynamicRef": { "type": "string", "description": "JSON Schema: a reference resolved in the dynamic scope." },
125
+ "$dynamicAnchor": { "type": "string", "description": "JSON Schema: an anchor for `$dynamicRef`." },
126
+ "$defs": { "$ref": "#/$defs/schemaMap", "description": "JSON Schema: schemas kept for `$ref`, by name." },
127
+ "$comment": { "type": "string", "description": "JSON Schema: a comment for the schema's authors." },
128
+
129
+ "allOf": { "$ref": "#/$defs/schemas", "description": "JSON Schema: the value is valid against every one of these." },
130
+ "anyOf": { "$ref": "#/$defs/schemas", "description": "JSON Schema: the value is valid against at least one of these." },
131
+ "oneOf": { "$ref": "#/$defs/schemas", "description": "JSON Schema: the value is valid against exactly one of these." },
132
+ "not": { "$ref": "#/$defs/schema", "description": "JSON Schema: the value is not valid against this." },
133
+ "if": { "$ref": "#/$defs/schema", "description": "JSON Schema: when the value is valid against this, `then` applies, else `else`." },
134
+ "then": { "$ref": "#/$defs/schema", "description": "JSON Schema: applies when `if` holds." },
135
+ "else": { "$ref": "#/$defs/schema", "description": "JSON Schema: applies when `if` does not hold." },
136
+ "dependentSchemas": { "$ref": "#/$defs/schemaMap", "description": "JSON Schema: per property name, a schema that applies when the property is present." },
137
+ "prefixItems": { "$ref": "#/$defs/schemas", "description": "JSON Schema: the schemas of the first items, in order." },
138
+ "items": { "$ref": "#/$defs/schema", "description": "JSON Schema: the schema of every item (after `prefixItems`)." },
139
+ "contains": { "$ref": "#/$defs/schema", "description": "JSON Schema: at least one item is valid against this." },
140
+ "properties": { "$ref": "#/$defs/schemaMap", "description": "JSON Schema: the schema of each property, by name. delurio's keywords may be used on each." },
141
+ "patternProperties": { "$ref": "#/$defs/schemaMap", "description": "JSON Schema: per regular expression, the schema of the properties whose names match it." },
142
+ "additionalProperties": { "$ref": "#/$defs/schema", "description": "JSON Schema: the schema of the properties not named in `properties` or `patternProperties`." },
143
+ "propertyNames": { "$ref": "#/$defs/schema", "description": "JSON Schema: the schema every property name is valid against." },
144
+ "unevaluatedItems": { "$ref": "#/$defs/schema", "description": "JSON Schema: the schema of the items no other keyword evaluated." },
145
+ "unevaluatedProperties": { "$ref": "#/$defs/schema", "description": "JSON Schema: the schema of the properties no other keyword evaluated." },
146
+
147
+ "type": {
148
+ "description": "JSON Schema: the value's type, or a list of types. `null` is a type like any other.",
149
+ "anyOf": [
150
+ { "$ref": "#/$defs/typeName" },
151
+ { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "$ref": "#/$defs/typeName" } }
152
+ ]
153
+ },
154
+ "const": { "description": "JSON Schema: the only value allowed." },
155
+ "enum": { "type": "array", "minItems": 1, "description": "JSON Schema: the values allowed. An enum that may be empty lists `null` among its values." },
156
+ "multipleOf": { "type": "number", "exclusiveMinimum": 0, "description": "JSON Schema: the number is a multiple of this." },
157
+ "maximum": { "type": "number", "description": "JSON Schema: the largest number allowed." },
158
+ "exclusiveMaximum": { "type": "number", "description": "JSON Schema: the number is less than this." },
159
+ "minimum": { "type": "number", "description": "JSON Schema: the smallest number allowed." },
160
+ "exclusiveMinimum": { "type": "number", "description": "JSON Schema: the number is greater than this." },
161
+ "maxLength": { "$ref": "#/$defs/nonNegative", "description": "JSON Schema: the longest string allowed, in characters." },
162
+ "minLength": { "$ref": "#/$defs/nonNegative", "description": "JSON Schema: the shortest string allowed, in characters." },
163
+ "pattern": { "type": "string", "description": "JSON Schema: a regular expression (ECMA-262) the string matches." },
164
+ "maxItems": { "$ref": "#/$defs/nonNegative", "description": "JSON Schema: the most items allowed." },
165
+ "minItems": { "$ref": "#/$defs/nonNegative", "description": "JSON Schema: the fewest items allowed." },
166
+ "uniqueItems": { "type": "boolean", "description": "JSON Schema: `true` when no two items may be equal." },
167
+ "maxContains": { "$ref": "#/$defs/nonNegative", "description": "JSON Schema: the most items valid against `contains`." },
168
+ "minContains": { "$ref": "#/$defs/nonNegative", "description": "JSON Schema: the fewest items valid against `contains`." },
169
+ "maxProperties": { "$ref": "#/$defs/nonNegative", "description": "JSON Schema: the most properties allowed." },
170
+ "minProperties": { "$ref": "#/$defs/nonNegative", "description": "JSON Schema: the fewest properties allowed." },
171
+ "required": { "$ref": "#/$defs/names", "description": "JSON Schema: the properties that must be present." },
172
+ "dependentRequired": {
173
+ "type": "object",
174
+ "description": "JSON Schema: per property name, the properties that must be present when it is.",
175
+ "additionalProperties": { "$ref": "#/$defs/names" }
176
+ },
177
+
178
+ "title": { "type": "string", "description": "JSON Schema: a short title." },
179
+ "description": { "type": "string", "description": "JSON Schema: what the value is, in words." },
180
+ "default": { "description": "JSON Schema: the value when none is given." },
181
+ "deprecated": { "type": "boolean", "description": "JSON Schema: `true` when the value should no longer be used." },
182
+ "readOnly": { "type": "boolean", "description": "JSON Schema: `true` when the value is set by the service, never by the caller." },
183
+ "writeOnly": { "type": "boolean", "description": "JSON Schema: `true` when the value is sent but never answered back." },
184
+ "examples": { "type": "array", "description": "JSON Schema: example values." },
185
+ "format": { "type": "string", "description": "JSON Schema: a format of the string.", "examples": ["date-time", "date", "email", "uri", "uuid", "hostname", "ipv4"] },
186
+ "contentEncoding": { "type": "string", "description": "JSON Schema: how the string encodes binary content.", "examples": ["base64"] },
187
+ "contentMediaType": { "type": "string", "description": "JSON Schema: the media type of the string's content.", "examples": ["text/calendar", "application/json"] },
188
+ "contentSchema": { "$ref": "#/$defs/schema", "description": "JSON Schema: the schema of the string's decoded content." },
189
+
190
+ "references": { "type": "string", "description": "delurio: the field holds the key of this other entity." },
191
+ "unique": {
192
+ "description": "delurio: no two entities have the same value: `true`, or `case-insensitive`.",
193
+ "enum": [true, "case-insensitive"]
194
+ },
195
+ "sensitivity": {
196
+ "description": "delurio: what may be shown, logged or kept. `credential`: never shown, logged or stored in clear. `personal`: data about a person. `internal`: never shown to users.",
197
+ "enum": ["credential", "personal", "internal"]
198
+ },
199
+ "owner": { "description": "delurio, capture only: a word the capture keeps on a field; no tool reads it." },
200
+ "note": { "description": "delurio, capture only: a word the capture keeps on a field; no tool reads it." },
201
+ "editableBy": { "description": "delurio, capture only: a word the capture keeps on a field; no tool reads it." },
202
+ "matching": { "description": "delurio, capture only: a word the capture keeps on a field (how values are compared, e.g. `exact`); no tool reads it." },
203
+ "opaque": { "description": "delurio, capture only: a word the capture keeps on a field (the value is passed on unread); no tool reads it." },
204
+ "source": { "$ref": "#/$defs/sourceAnchor" }
205
+ }
206
+ },
207
+ "action": {
208
+ "type": ["object", "null"],
209
+ "description": "An action. With a `route` it is one OpenAPI 3.1 operation: its name is the operationId, `needs` its security requirement, `query` its query parameters, `body` its request body, `result` its response, and each refusal one more response.",
210
+ "additionalProperties": false,
211
+ "properties": {
212
+ "route": {
213
+ "type": "string",
214
+ "description": "`METHOD /path`: the HTTP method and the path of the operation. An action with no route is a step inside the service.",
215
+ "pattern": "^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS|TRACE) /\\S*$",
216
+ "examples": ["POST /authorize/consent", "GET /w/{workspace}/projects"]
217
+ },
218
+ "operationId": { "type": "string", "description": "The operation in the app's own OpenAPI document (named at the top with `openapi:`), when it is not this action's name." },
219
+ "summary": { "type": "string", "description": "OpenAPI: the operation in a few words." },
220
+ "description": { "type": "string", "description": "OpenAPI: what the operation or the step does, in words." },
221
+ "needs": { "type": "string", "description": "delurio: what the caller must hold (the operation's security requirement).", "examples": ["session"] },
222
+ "query": { "$ref": "#/$defs/schema", "description": "The query parameters: a JSON Schema object." },
223
+ "body": { "$ref": "#/$defs/schema", "description": "The request body: a JSON Schema." },
224
+ "result": { "$ref": "#/$defs/result" },
225
+ "refusals": {
226
+ "type": "object",
227
+ "description": "Each way the action refuses, by refusal code; each is one more response of the operation. A flow's `failures` sort the codes into classes.",
228
+ "additionalProperties": { "$ref": "#/$defs/refusal" }
229
+ },
230
+ "sideEffects": {
231
+ "type": "array",
232
+ "description": "delurio: what else the action does, each in words or as `<kind>:<event>`.",
233
+ "items": { "type": "string" },
234
+ "examples": [["audit:consent.decided"]]
235
+ },
236
+ "note": { "type": "string", "description": "The author's own words about the action, which no tool reads (SPEC.md §5)." },
237
+ "source": { "$ref": "#/$defs/sourceAnchor" }
238
+ }
239
+ },
240
+ "result": {
241
+ "type": "object",
242
+ "description": "The action's response: `returns` an entity, a `redirect`, a `status`, or a JSON Schema.",
243
+ "$ref": "#/$defs/keywords",
244
+ "properties": {
245
+ "returns": { "type": "string", "description": "The entity the action returns." },
246
+ "redirect": { "type": "string", "description": "Where the response redirects, in words or as a path." },
247
+ "status": { "type": "integer", "minimum": 100, "maximum": 599, "description": "The HTTP status of the response." }
248
+ },
249
+ "unevaluatedProperties": false
250
+ },
251
+ "refusal": {
252
+ "type": "object",
253
+ "description": "A refusal: one more response of the operation.",
254
+ "additionalProperties": false,
255
+ "properties": {
256
+ "status": { "type": "integer", "minimum": 100, "maximum": 599, "description": "The HTTP status of the refusal." },
257
+ "redirect": {
258
+ "type": "string",
259
+ "description": "delurio: whether and where the refusal redirects, e.g. `never` (a page is shown), `error` (back to the caller with the error), `retry`, or a path.",
260
+ "examples": ["never", "error", "retry"]
261
+ },
262
+ "body": { "$ref": "#/$defs/schema", "description": "The refusal's body: RFC 9457 problem details whose `type` is the refusal code." },
263
+ "note": { "type": "string", "description": "The author's own words about the refusal, which no tool reads (SPEC.md §5)." },
264
+ "source": { "$ref": "#/$defs/sourceAnchor" }
265
+ }
266
+ },
267
+ "policy": {
268
+ "type": "object",
269
+ "description": "Who may do what to which data.",
270
+ "required": ["actor"],
271
+ "additionalProperties": false,
272
+ "properties": {
273
+ "actor": { "type": "string", "description": "Who the policy is for.", "examples": ["end-user", "anyone", "agent"] },
274
+ "needs": { "type": "string", "description": "What the actor must hold.", "examples": ["session"] },
275
+ "where": { "type": "string", "description": "The condition under which it holds, in words." },
276
+ "read": { "$ref": "#/$defs/names", "description": "The entities the actor may read." },
277
+ "write": { "$ref": "#/$defs/names", "description": "The entities the actor may write." },
278
+ "do": { "$ref": "#/$defs/names", "description": "The actions the actor may invoke." },
279
+ "source": { "$ref": "#/$defs/sourceAnchor" }
280
+ }
281
+ },
282
+ "invariant": {
283
+ "type": "object",
284
+ "description": "Something that must always hold.",
285
+ "required": ["id", "rule"],
286
+ "additionalProperties": false,
287
+ "properties": {
288
+ "id": { "type": "string", "description": "The invariant's id.", "examples": ["redirect-uri-exact"] },
289
+ "rule": { "type": "string", "description": "The rule, in words." },
290
+ "spec": { "type": "string", "description": "The standard and section it comes from, cited, never written again.", "examples": ["RFC 6749 §3.1.2.3"] },
291
+ "holds": { "type": "boolean", "default": true, "description": "`false` when the code does not keep the invariant: it is still written, as what should hold, with the `finding` that says where it does not. `true` when left out." },
292
+ "finding": { "type": "string", "description": "The finding that reports where the code breaks the invariant: its id in the graph's report. Required with `holds: false`.", "examples": ["MS-7"] },
293
+ "note": { "type": "string", "description": "The author's own words about the invariant, which no tool reads (SPEC.md §5)." },
294
+ "source": { "$ref": "#/$defs/sourceAnchor" }
295
+ },
296
+ "allOf": [
297
+ {
298
+ "$comment": "an invariant the code does not keep names the finding that reports it",
299
+ "if": { "properties": { "holds": { "const": false } }, "required": ["holds"] },
300
+ "then": { "required": ["finding"] }
301
+ }
302
+ ]
303
+ }
304
+ }
305
+ }