Skip to main content

Variable: Envelope

const Envelope: TObject<{ actor: TUnion<[TObject<{ kind: TLiteral<"tenant">; roles: TArray<TString>; scopePath: TString; subjectId: TString; tenant: TString; }>, TObject<{ kind: TLiteral<"platform">; roles: TArray<TString>; scopePath: TLiteral<"/">; subjectId: TLiteral<"00000000-0000-0000-0000-000000000000">; tenant: TLiteral<"platform">; }>]>; actorToken: TOptional<TString>; callerModule: TOptional<TUnsafe<"identity" | "audit" | "governance" | "trust" | "issuance" | "verification" | "vault" | "signing" | "e-services" | "provisioning">>; causationId: TString; correlationId: TString; deadline: TOptional<TString>; idempotencyKey: TOptional<TString>; issuedAt: TString; messageId: TString; schema: TString; }>

Defined in: packages/contracts/src/envelope.ts:120

The envelope every message carries, as NATS headers (never in the body, so the body is exactly the registered schema).

idempotencyKey is optional here and REQUIRED on every mutation, which checkEnvelope enforces against the subject's registration: the one place it is forgotten is the one that double-issues. deadline is the absolute time after which a receiver drops the message rather than doing work its caller has abandoned; it is required on requests.

Two fields prove who is behind the message (D2.2), and both are optional in the schema because neither is on every message; the receiver decides when each is required:

  • actorToken is the gateway's signed proof of actor for this one message (ActorTokenClaims). The receiver requires it on every message from the gateway (from step 2.4), and a module-initiated call passes it on unchanged.
  • callerModule names the module that made a module-initiated call. Only the in-process transport writes it, from the wiring, and over the broker it is refused because nothing there proves which module of a deployable published.