Component Licence File Contract v1

Contract: stella.ops/componentLicence@v1 (CONTRACT-COMPONENT-LICENCE-FILE-V1-075). Schema: component-licence-file.v1.schema.json (JSON Schema 2020-12, the payload). DSSE payload type: application/vnd.stellaops.component-licence.v1+json. Signature algorithm: ES256 (ECDSA P-256 with SHA-256; the signature is the 64-byte r || s concatenation). Signing root: a root of purpose vendor-entitlement in the vendor trust-root set. Examples: valid payload, invalid payload. Implementation: src/__Libraries/StellaOps.Components.Licensing/ (ComponentLicenceVerifier, ComponentLicenceFileParser, ComponentLicenceTrustRoots, ComponentLicenceLoader, ComponentLicenceEvaluator, ComponentLicenceNotice, ComponentLicenceNoticeFormatter); tests in src/__Libraries/__Tests/StellaOps.Components.Licensing.Tests/, which also hold the examples and schema to this contract. Issuer: src/Tools/StellaOps.EntitlementIssuer (issue-component), see the issuer runbook.


Purpose and boundary

A component licence record records, for one Installation, the production-permission lines of the customer’s order: one line per component (the Router, the Workflow engine, or both), each with the licensee display name agreed for it and its entitlement entries. Stella Ops signs it; the customer supplies it to the components as a file or as a key (the same signed record as one base64 text value). Each component reads it offline, reads only its own line, reports a status and shows a licence notice. In this contract “licence file” means the record in either form.

The record evidences the order:

The record is limited to closed licence administration between Stella Ops, the customer of the order, each end customer named for an embedded line of the identified Installation and bound by the applicable licence-administration terms, and the persons who administer that Installation for them:

What a loaded record shows

A record whose signature matches a pinned vendor-entitlement root shows only:

It does not show that any count is correct, that the Installation is used as the order describes, that a use is within an embedded line’s named product, or that an Installation without a record, or with an older record, lacks a permission: the free limits and every other permission of the component licence apply independently.

Envelope

The file is a DSSE envelope (JSON), exchanged as a .dsse.json file:

{
  "payloadType": "application/vnd.stellaops.component-licence.v1+json",
  "payload": "<base64 of the canonical payload bytes>",
  "signatures": [
    { "keyid": "<issuerKeyId>", "sig": "<base64 of the ES256 signature>" }
  ]
}

File or key

The same signed record is accepted in two forms with the same role:

SettingForm
StellaOps:ComponentLicence:PathA licence file, or a directory whose *.dsse.json files are read (at most 64, in ordinal name order). Local path only.
StellaOps:ComponentLicence:KeyThe licence key: the standard base64 encoding (RFC 4648, with padding) of the licence file, as one line. White space around it is ignored; any other character refuses it.

Base64 is an encoding, not a protection: the key is the same public, signed record as the file, and it is verified exactly as the file. When both settings are set, the component reads neither and reports one record not loaded with the refusal conflicting_sources, so the ambiguity shows in the licence details instead of one setting silently shadowing the other. With neither, no record is read.

Payload fields

All fields are required, and no other field is allowed, at any level.

FieldTypeMeaning
schemaVersionstringstella.ops/componentLicence@v1.
purposestringlicence-administration: the only purpose of the record.
serialstringThe opaque record identifier: the record of one Installation for its whole life, ^[A-Z0-9][A-Z0-9-]{2,63}$.
revisionintegerRevision of the serial, from 1.
issuerKeyIdstringKey identifier of the vendor-entitlement root that signs this revision: sha256: and the lowercase hexadecimal SHA-256 of the key’s SubjectPublicKeyInfo.
installationIdstringThe opaque Installation identifier the components are configured with, a random lowercase UUID. Every line is for this Installation.
issuedAtstringTime the issuer signed this revision, UTC, YYYY-MM-DDTHH:MM:SSZ. Informational.
linesarrayOne or two lines, at most one per component.

Each line has exactly these fields:

FieldTypeMeaning
componentstringrouter or workflow.
permissionstringstandard-capacity or embedded (below).
licenseeDisplayNamestringThe organisation name, trading name or neutral display label agreed for this line in the order, shown in the licence notice. 1 to 128 Unicode characters: letters, combining marks, decimal digits, the punctuation ! " & ' ( ) , . / : + - and the quotation marks «, », ’, “, ” and „, with single spaces between words and at least one letter or digit. No control, format or markup character, and no leading or trailing space.
entriesarrayThe line’s entitlement entries, in the form of its permission.

A standard-capacity line has 1 to 64 entries, in strictly ascending order of coversVersionsPublishedBefore, each with exactly these fields:

FieldTypeMeaning
capacityintegerThe recorded capacity as a total, 1 to 1,000,000: Endpoints for the Router, Designated Workflows for the Workflow engine. The order buys capacity in whole blocks above the free limit; the issuer computes the total from the blocks the order records, and the record carries the total.
coversVersionsPublishedBeforestringThe entry’s release-date scope: it covers the versions first published before this date. A UTC calendar date YYYY-MM-DD, exclusive.
orderReferencestringReference of the order or transaction that records the entry: ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$.

There is one entry per capacity level and release-date scope. The capacity of an entry is a total; it is never added to another entry’s capacity.

An embedded line records the permission of an accepted order for the customer’s named product on the named end-customer Installation. It has exactly one entry, with exactly these fields:

FieldTypeMeaning
capacitystringunlimited, for the component within the named product on that Installation.
versionScopestringdelivered-without-cutoff: any version of the component that the customer delivers to the named end customer as part of the named product, including versions first published later. The entry has no release-date cutoff, and no date stands in for one.
effectiveDatestringThe UTC calendar date YYYY-MM-DD on which the order granting the line was accepted.
orderReferencestringReference of the order that records the line.

The order references of a line are the orderReference values of its entries. The record carries no named-product or end-customer field: the order identifies them, and the display name of an embedded line is the label agreed for the end customer.

Verification rules

The component verifies each record on its own and loads it only when every check passes. A record that is not loaded counts for nothing, and the reason is shown as a detail. The refusal codes are:

CodeCause
unreadableThe file could not be read, the path does not exist, or a directory holds more than 64 licence files.
malformed_envelopeThe file is empty, larger than 64 KiB, or not a DSSE envelope with exactly the three fields and base64 values; or the key is not one line of standard base64 or longer than a file can be.
unsupported_payload_typeThe payload type is not the one above.
missing_signatureThe envelope has no signature.
non_canonical_payloadThe payload is not in its canonical form (Stella Ops canonical JSON version 1, see above).
schema_violationThe payload does not match the schema or the rules above (field sets at every level, patterns, licensee display names, one line per component, the entry form of each permission, ascending dates). A field the contract does not define, such as a contact or e-mail field, is refused at every level.
no_trust_rootsNo vendor-entitlement root is usable (see Trust roots).
unknown_keyissuerKeyId names no active root, or a superseded one.
issuer_key_mismatchNo signature carries the payload’s issuerKeyId.
signature_invalidNo signature with that key identifier matches the payload under the root.
wrong_installationinstallationId is not the identifier the component is configured with, or none is configured.
wrong_componentThe record carries no line for the component that reads it.
conflicting_sourcesBoth StellaOps:ComponentLicence:Path and StellaOps:ComponentLicence:Key are set; neither is read.

Trust roots

Supersede and continuity rules

Evaluation

The component evaluates its status from three inputs: its local count, its own lines of the loaded records, and the first-publication date of the running version.

The first status that holds is reported:

StatusWhenMessage
count-unavailableThe Workflow engine’s local workflow-name count is unavailable.The local workflow-name count is unavailable.
within-free-limitThe count is at or below the notice level. No record is needed.Router: Local Endpoint count: [count]. Workflow: Recorded workflow-name count: [count].
embedded-scope-not-establishedThe count is above the notice level, and an embedded entry decides.The local record does not establish that this use is within its named product and end-customer Installation scope. Check the applicable Order and any other permission.
record-matchesThe count is above the notice level, a standard-capacity entry covers the running version, and the count is within its capacity or the free limit.This record covers versions first published before [date].
count-exceeds-recorded-capacityThe count is above the free limit and above the capacity of the standard-capacity entry that decides.The local assessment could not confirm recorded capacity for this version and count. Check the applicable LICENSE, Order and any other permission.
above-notice-levelThe count is above the notice level and within the free limit, and no entry covers the running version.Router: Local Endpoint count: [count]. This is above the [notice level]-Endpoint notice level. Check permitted use under the applicable LICENSE and any Order. Workflow: Recorded workflow-name count: [count]. This is above the [notice level]-name notice level. This technical count is not the contractual Designated Workflow count.
development-buildThe count is above the free limit, no entry covers the running version, and the running build has no first-publication date. The details add: This build carries no first-publication date, so the licence records are not assessed.The local assessment could not confirm recorded capacity for this version and count. Check the applicable LICENSE, Order and any other permission.
no-matching-recordThe count is above the free limit, and no loaded entry covers the running version. The details show the date of every loaded entry in the record-matches message form.The local assessment could not confirm recorded capacity for this version and count. Check the applicable LICENSE, Order and any other permission.

Messages suggesting missing capacity are suppressed when an applicable standard-capacity entry covers the running version and the count. within-free-limit and record-matches are written to the log on a change; every other status is a warning in the log at startup and hourly (ComponentLicenceAssessment.Warns). Nothing is refused, and readiness and liveness never change. The licence-status explanation accompanies the messages:

The notice levels are informational and are below the standard free-production limits of [free limit] Endpoints for Router and [free limit] Designated Workflows for Workflow. Crossing a notice level does not itself establish that additional production permission is required and does not create a fee. The applicable LICENSE, any Order and other independently applicable permissions determine permitted use.

No status or message says that an Installation is unlicensed, non-compliant or expired, and none states free use. The status describes the records available to the local reader; it is not a determination of the customer’s legal entitlement or compliance, and the absence of a warning is not a compliance attestation.

Licence notice

The component also shows a licence notice: the Workflow engine in its SVG renders, its startup log and an hourly log line, and its health and licence API output; the Router in its logs and its health output. The notice is built from the evaluation (ComponentLicenceNotice), so its licensee comes only from a record that is authenticated and carries a line for the component and the Installation. The first case that holds applies:

CaseNotice
An entry of the component’s line covers the running version. With several loaded records, the line of the highest applicable entry decides.Licensed to [licenseeDisplayName]
No licence record is read.No local licence record is loaded. See the applicable LICENSE and Order for permitted use.
Licence records are read, and none is in force (each is not loaded, carries no line for the component, or conflicts with another file of the same revision).The local licence record could not be authenticated or matched to this Installation.
Standard-capacity records are in force, and the running build carries no first-publication date.This build carries no first-publication date, so the licence records are not assessed.
Standard-capacity records are in force, and no standard-capacity entry covers the running version ([date] is the latest cutoff).This record covers versions first published before [date]. It does not record paid coverage for this version.

“Licensed to [licenseeDisplayName]” identifies the local licence record. It does not certify the author, content, authenticity or compliance of a workflow, diagram or other customer output. A diagram carrying the label may be shared; it is not a vendor-signed assertion about customer output.

The one-line form for logs and health output (ComponentLicenceNoticeFormatter.Format) follows the notice with its fields, separated by |:

Licensed to Northwind Traders Ltd. | component: router | licensed capacity: 1000 | covers versions first published before: 2027-11-03 | status: record-matches | licence records in force: 2, the highest applicable entry applies
Licensed to Fabrikam Clinics | component: workflow | permission: embedded | licensed capacity: unlimited | version scope: delivered-without-cutoff | effective date: 2026-12-01 | status: embedded-scope-not-established

The licensed capacity and the date appear only with a covering entry; an embedded line shows its permission, unlimited capacity, version scope and effective date instead of a cutoff. licence records in force appears when several records are in force, and licence files not loaded: [n] when a record that was read is not loaded. The licensee display name holds no control or markup character, so a log line takes it unchanged; an SVG or HTML renderer escapes &, ' and " as its format requires.

Issuance

The vendor issues records offline with the entitlement issuer’s issue-component command, from an order record stella.ops/componentLicenceOrder@v1 that lists the Installation’s lines: for each, its component, permission, licensee display name and entries (a standard-capacity entry with its blocks, cutoff and order reference; an embedded entry with its effective date and order reference). The issuer signs only with an active vendor-entitlement root, computes each standard-capacity entry’s total from its blocks, checks the signed record with the verifier above for every line, as a file and as a key, before releasing it, refuses a revision that drops or lowers an entry of the previous revision unless the order record names it as a correction, and records each issuance, with every line’s component, permission, licensee display name and order references, in its append-only ledger. It writes the .dsse.json file and prints the licence key. The customer sends its Installation identifier and the display name agreed for each line; there is no activation server. A missing, inaccurate or mismatched record is delivered or corrected on request, for standard-capacity and embedded lines alike, at the request of the customer or of an end customer named for an embedded line. Procedure: issuer runbook and fulfilment runbook.

Examples

The examples are payloads only. A real record is signed by the vendor entitlement key, which is never present in the product or in this repository; tests sign with ephemeral keys they generate.

Change log

DateChange
2026-11-03v1 published.