@fabrika/provider-contract 0.3.3 → 0.4.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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/control.ts +83 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabrika/provider-contract",
3
- "version": "0.3.3",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,6 +31,6 @@
31
31
  "test": "bun test"
32
32
  },
33
33
  "dependencies": {
34
- "@fabrika/auth-core": "^0.3.3"
34
+ "@fabrika/auth-core": "^0.4.1"
35
35
  }
36
36
  }
package/src/control.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { AppSchema, ContractArtifact } from '@fabrika/auth-core'
1
2
  import type { JsonValue, ProviderEnvelope } from './json'
2
3
 
3
4
  /** Events whose persistence and presentation belong to the control plane. */
@@ -40,6 +41,18 @@ export interface ProviderDeploymentNamespace {
40
41
  readonly target: ProviderEnvelope
41
42
  }
42
43
 
44
+ /**
45
+ * The access Control approved for one application environment (ADR-0050): the contract the proxy enforces and the
46
+ * IAM vocabulary compiled from it. A provider publishes a contract application's endpoint table and reconciles its
47
+ * IAM schema from this, never from the artifact or a runner's report.
48
+ */
49
+ export interface ProviderApprovedAccess {
50
+ readonly contract: ContractArtifact
51
+ /** `contractDigest(contract)`, which the application compares with `FABRIKA_CONTRACT_DIGEST` at startup. */
52
+ readonly contractDigest: string
53
+ readonly schema: AppSchema
54
+ }
55
+
43
56
  /** Persisted deploy data for one app environment. */
44
57
  export interface ProviderEnvironment {
45
58
  readonly appId: string
@@ -50,6 +63,11 @@ export interface ProviderEnvironment {
50
63
  readonly namespace?: ProviderDeploymentNamespace
51
64
  readonly target: ProviderEnvelope
52
65
  readonly artifact: ProviderEnvelope
66
+ /**
67
+ * The environment's approved contract, from Control's `approvedSnapshot`. Absent when nothing is approved: then a
68
+ * provider publishes no endpoint table and reconciles no IAM schema, whatever the artifact claims (ADR-0050).
69
+ */
70
+ readonly access?: ProviderApprovedAccess
53
71
  }
54
72
 
55
73
  /** Raw registration data passed to provider-owned validation and normalization. */
@@ -272,6 +290,18 @@ export interface ProviderNamespaceMember {
272
290
  readonly env: string
273
291
  readonly domain?: string
274
292
  readonly artifact: ProviderEnvelope
293
+ /**
294
+ * The secret the namespace proxy authenticates itself to this application environment with (ADR-0022 rule 5).
295
+ * Control generates it once and keeps it in its vault; absent when Control has no vault.
296
+ */
297
+ readonly proxySecret?: string
298
+ /**
299
+ * The origin of this environment's active Operations ingest DSN, never the DSN itself: a contract application's
300
+ * proxy admits it in `connect-src`, as the framework does. Absent while the environment has no active ingest.
301
+ */
302
+ readonly operationsOrigin?: string
303
+ /** See `ProviderEnvironment.access`: the proxy table of a contract application comes only from here. */
304
+ readonly access?: ProviderApprovedAccess
275
305
  }
276
306
 
277
307
  /** One idempotent namespace lifecycle invocation. */
@@ -295,6 +325,51 @@ export interface ProviderNamespaceRepublishInput extends ProviderNamespaceMutati
295
325
  readonly wait: 'started' | 'active'
296
326
  }
297
327
 
328
+ /**
329
+ * The `code` of a `ProviderNamespaceError` an update plan throws when the requested target changes
330
+ * something the provider cannot move in place. Core answers it as a conflict that names the supported path.
331
+ */
332
+ export const PROVIDER_NAMESPACE_IMMUTABLE = 'namespaceImmutable'
333
+
334
+ /**
335
+ * The `code` of a `ProviderNamespaceError` an update apply throws when the live change MAY have been made
336
+ * and is not confirmed. Any other failure means nothing changed. Applying the same plan again must converge.
337
+ */
338
+ export const PROVIDER_NAMESPACE_UPDATE_UNCONFIRMED = 'namespaceUpdateUnconfirmed'
339
+
340
+ /** One provider-described change, safe to audit: names and values only, never a credential. */
341
+ export interface ProviderNamespaceChange {
342
+ readonly field: string
343
+ readonly from: string | null
344
+ readonly to: string
345
+ }
346
+
347
+ /** The validated result of merging a requested target over the stored one. `change` is null for a no-op. */
348
+ export interface ProviderNamespaceUpdatePlan {
349
+ readonly namespace: ProviderDeploymentNamespace
350
+ readonly change: ProviderNamespaceChange | null
351
+ }
352
+
353
+ /** Apply one plan. `next` is the planned namespace, with the same coordinates as `namespace`. */
354
+ export interface ProviderNamespaceUpdateInput {
355
+ readonly namespace: ProviderDeploymentNamespace
356
+ readonly next: ProviderDeploymentNamespace
357
+ /** The namespace an earlier, unconfirmed update planned; the live resources may already match it. */
358
+ readonly unconfirmed?: ProviderDeploymentNamespace
359
+ readonly signal: AbortSignal
360
+ }
361
+
362
+ /** In-place change of a settled namespace. */
363
+ export interface ProviderNamespaceUpdates {
364
+ /**
365
+ * Merge `requested` — whose payload may name only what changes — over the stored `namespace` and
366
+ * validate the result. Pure. A change that cannot be made in place throws `PROVIDER_NAMESPACE_IMMUTABLE`.
367
+ */
368
+ plan(namespace: ProviderDeploymentNamespace, requested: ProviderEnvelope): ProviderNamespaceUpdatePlan
369
+ /** Move the live resources to `next` and return the target core stores. */
370
+ apply(input: ProviderNamespaceUpdateInput): Promise<ProviderDeploymentNamespace>
371
+ }
372
+
298
373
  /** One registration whose provider coordinates do not exist until namespace services are prepared. */
299
374
  export interface ProviderRegistrationPreparationInput {
300
375
  readonly registration: ProviderRegistration
@@ -382,6 +457,8 @@ export interface ProviderNamespaceCapabilities {
382
457
  reconcile(input: ProviderNamespaceMutationInput): Promise<ProviderDeploymentNamespace>
383
458
  /** Absent means the namespace has no entry point that follows its members. */
384
459
  republish?(input: ProviderNamespaceRepublishInput): Promise<ProviderNamespaceRepublishResult>
460
+ /** Absent means the provider changes no namespace in place. */
461
+ readonly updates?: ProviderNamespaceUpdates
385
462
  readonly operator?: ProviderNamespaceOperator
386
463
  }
387
464
 
@@ -413,4 +490,10 @@ export interface ControlProvider {
413
490
  * manifest — constrains what an operator may set.
414
491
  */
415
492
  declaredVariables?(input: { readonly artifact: ProviderEnvelope }): readonly string[] | undefined
493
+ /**
494
+ * The repository-relative directory this provider executes the application from, normalized as its execution
495
+ * normalizes it (`''` for the repository root), or null for a root execution refuses. Control reads the run's
496
+ * access snapshot there (ADR-0050). Absent means the repository root.
497
+ */
498
+ applicationRoot?(source: ProviderSource): string | null
416
499
  }