@inixiative/signet 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inixiative/signet",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "Present Kingdom Signets: the wire contracts, DPoP proofs, device pairing and a renewing client shared by Kingdom, Archive, Foundry and Oracle.",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -35,7 +35,7 @@
35
35
  "devDependencies": {
36
36
  "@asteasolutions/zod-to-openapi": "^9.1.0",
37
37
  "@biomejs/biome": "2.5.2",
38
- "@inixiative/config": "^0.5.174",
38
+ "@inixiative/config": "^0.5.175",
39
39
  "@inixiative/json-rules": "^3.16.0",
40
40
  "@types/bun": "1.4.4",
41
41
  "lefthook": "2.1.9",
package/src/archive.ts CHANGED
@@ -1,5 +1,6 @@
1
+ import type { Condition } from '@inixiative/json-rules';
1
2
  import { z } from 'zod';
2
- import { type GrantLens, projectionFilters, projectionShows } from './lens';
3
+ import { type GrantLens, type LensLayer, projectionFilters, projectionShows } from './lens';
3
4
  import { type OperationScope, scopeRefusal } from './operations';
4
5
 
5
6
  /**
@@ -12,7 +13,14 @@ export const archiveLibraryResourceKind = 'archiveLibrary';
12
13
 
13
14
  /** An Archive session id: `archiveKey(snapshot)`, the digest of its source and session. */
14
15
  export const archiveDocumentIdSchema = z.string().regex(/^[a-f0-9]{64}$/);
15
- export const archiveFieldSchema = z.enum(['id', 'title', 'content', 'tags', 'createdAt']);
16
+ export const archiveFieldSchema = z.enum([
17
+ 'id',
18
+ 'title',
19
+ 'content',
20
+ 'tags',
21
+ 'projectId',
22
+ 'createdAt',
23
+ ]);
16
24
  export type ArchiveField = z.infer<typeof archiveFieldSchema>;
17
25
 
18
26
  /** The operations an `archiveLibrary` resource carries. */
@@ -42,7 +50,7 @@ export const archiveSourceOperations = [
42
50
  export const isArchiveSourceOperation = (operation: ArchiveOperation) =>
43
51
  (archiveSourceOperations as readonly ArchiveOperation[]).includes(operation);
44
52
 
45
- const fieldsSchema = z.array(archiveFieldSchema).min(1).max(5);
53
+ const fieldsSchema = z.array(archiveFieldSchema).min(1).max(archiveFieldSchema.options.length);
46
54
 
47
55
  /**
48
56
  * The input each Archive operation takes. `access/execute` carries the same fields beside
@@ -90,6 +98,40 @@ export const archiveLensRefusal = (operation: ArchiveOperation, lens: GrantLens)
90
98
  return null;
91
99
  };
92
100
 
101
+ type ArchiveInput<O extends ArchiveOperation> = z.infer<(typeof archiveInputSchemas)[O]>;
102
+
103
+ /**
104
+ * What one call filters on, as a json-rules condition over the Archive document, or undefined when
105
+ * it filters on nothing. Kingdom gates it with `validateRuleInLens` against the grant's composed
106
+ * lens: a filter on a field the lens hides (`projectId`, a `tag`) would say which documents carry a
107
+ * value the holder can't see, and is refused with the lens's own code.
108
+ */
109
+ export const archiveCallCondition = <O extends ArchiveOperation>(
110
+ _operation: O,
111
+ input: ArchiveInput<O>,
112
+ ): Condition | undefined => {
113
+ const rules: Condition[] = [
114
+ ...('projectId' in input && input.projectId !== undefined
115
+ ? [{ field: 'projectId', operator: 'equals' as const, value: input.projectId }]
116
+ : []),
117
+ ...('tag' in input && input.tag !== undefined
118
+ ? [{ field: 'tags', operator: 'contains' as const, value: input.tag }]
119
+ : []),
120
+ ];
121
+ return rules.length === 0 ? undefined : rules.length === 1 ? rules[0] : { all: rules };
122
+ };
123
+
124
+ /**
125
+ * The fields one call asks for, as a lens layer that picks them, or undefined when it asks for none.
126
+ * Kingdom validates it under the grant's composed lens (`validateNarrowing`): a field the lens hides
127
+ * is refused there.
128
+ */
129
+ export const archiveCallNarrowing = <O extends ArchiveOperation>(
130
+ _operation: O,
131
+ input: ArchiveInput<O>,
132
+ ): LensLayer | undefined =>
133
+ 'fields' in input && input.fields?.length ? { root: { picks: [...input.fields] } } : undefined;
134
+
93
135
  /** `archiveLensRefusal` over every operation a grant row reaches, `full` meaning all of them. */
94
136
  export const archiveGrantRefusal = (scope: OperationScope, lens: GrantLens) =>
95
137
  scopeRefusal(scope, archiveOperationSchema.options, (operation) =>
package/src/contracts.ts CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  signetGrantSchema,
15
15
  signetResourceSchema,
16
16
  } from './grants';
17
- import { storedLensLayersSchema } from './lens';
17
+ import { storedBaseLensSchema, storedLensLayersSchema } from './lens';
18
18
  import {
19
19
  foundryIdSchema,
20
20
  threadFloorActionSchema,
@@ -280,6 +280,8 @@ export const hostedSignetSchema = z.object({
280
280
  id: z.uuid(),
281
281
  displayName: z.string(),
282
282
  }),
283
+ /** Each base lens the rows' `lens` layers compose under, keyed by `baseLensId(provider, kind)`. */
284
+ baseLenses: z.record(z.string(), storedBaseLensSchema),
283
285
  resources: grantsSchema,
284
286
  });
285
287
  export type InstallationSignet = z.infer<typeof installationSignetSchema>;
package/src/lens.ts CHANGED
@@ -34,6 +34,19 @@ export const storedLensLayerSchema = z.strictObject({
34
34
  });
35
35
  export const storedLensLayersSchema = z.array(storedLensLayerSchema).max(20);
36
36
 
37
+ /**
38
+ * A base lens as Kingdom's catalog carries it: the json-rules `Lens` itself (its field maps, map name
39
+ * and model) with an `id` and no parents. Only the envelope is checked here; a holder composes it
40
+ * under a grant's layers with json-rules `composeLens`, which validates what is inside.
41
+ */
42
+ export const storedBaseLensSchema = z.looseObject({
43
+ id: layerId,
44
+ parents: z.array(layerId).max(0),
45
+ mapName: z.string().min(1),
46
+ model: z.string().min(1),
47
+ maps: z.record(z.string(), z.unknown()),
48
+ });
49
+
37
50
  /** The id of an integration's base lens for a resource kind's model, in Kingdom's catalog. */
38
51
  export const baseLensId = (provider: string, kind: string) => `${provider}:${kind}`;
39
52