Orishare
Concepts

Configuration as code

Export an environment as one JSON document and apply it to another, atomically: the v2 format, revisions, preview, merge semantics and the diff.

GET /v1/config/export?schema=orishare.config/v2 returns the whole configuration of the environment as one portable document: resources (currencies, attribute and event definitions, segments, counters), programs with their versions, seasons, rules with their versions, catalogues, offers, inventories, code_pools, assets, presentation, trust_policy and the project context. Entries refer to each other by key, so the document applies to another environment. No secrets are exported.

Always ask for orishare.config/v2. Without schema the export is the older orishare.config/v1, which has no revision protection and is refused with 409 config_format_required in any environment that has native programs, seasons, catalogues, currency capabilities or v2 rules. (legacy_only=true exports just the v1 part, for tools that still read v1.)

Revisions

The v2 export carries the environment's configuration revision in the Configuration-Revision response header (also the ETag, and Configuration-Environment names the environment). It is not part of the document, so read it from the raw response. It identifies the state you read.

POST /v1/config/apply takes { "document", "mode", "expected_revision" }:

  • mode: "preview" plans the change and writes nothing. With expected_revision it also refuses with 409 stale_write if the target changed since that revision.
  • mode: "apply" requires expected_revision (409 stale_write without it, or when the target moved) and runs everything in one transaction. Unknown references, invalid rules and immutable changes (currency precision, counter shape, a held tier level) fail with validation_failed naming the path, and nothing is applied.

Both answers carry revision: the revision the request was checked against, not the revision after the apply. To learn the new revision, export again. Applying the same document twice is a no-op (changes: 0). Publishing rules in a production environment requires the owner or admin role (or a secret key with rules:publish).

Apply is a merge

Apply creates what the document has and the target lacks, and updates what both have and that differs. It never deletes: a resource, program or rule the target has and the document omits is left as it is. To retire something, keep it in the document with its archived status (for example "status": "archived" on a program or rule). The usual flow is to export, edit the exported document and apply it whole.

Version digests are server-computed. Each program, season and rule row carries versions[].digest and a head ({ version, digest }) that must name one of its versions. The digest is a hash the server computes over the normalized definition, its bindings and its dependencies; it is checked on apply (validation_failed when it does not match) and is not a documented algorithm to reproduce. Copy versions and heads unchanged from an export (of this or another environment), and change other fields around them. To add a new rule, do not write a rule row by hand: propose a rule.create change set, then rule.publish_draft with key set to the created rule's id (outcome.result.id of the first commit) and expected_version set to outcome.result.version (Author a mechanic). The rule then appears in the next export with its digests.

The answer

FieldMeaning
mode, appliedWhat ran; applied is true only for mode: "apply".
diffPer section (resources, programs, rules, ...), the entries under create, update and unchanged.
changesThe number of create plus update entries.
published_rulesThe ids of the document's rules whose status is published, changed or not; empty with publish: false.
notesPlain-language notes about the plan.
revisionThe revision the request was checked against.

A diff entry is a JSON-encoded tuple [kind, catalogue, key, version], with null for the parts a section does not use: "[\"event_definition\",null,\"article_shared\",null]" is the event definition article_shared, "[\"streak\",null,\"daily_lessons\",null]" the streak program daily_lessons. Parse it with JSON.parse. Single-object sections (presentation, trust_policy, context) use the section name as the entry. There is no delete list, because apply never deletes.

Over HTTP and with the CLI

# Export, keeping the revision.
curl -sD headers.txt "$API/v1/config/export?schema=orishare.config/v2" \
  -H "Authorization: Bearer $ORISHARE_SECRET_KEY" > config.json

# Preview, then apply exactly what was reviewed.
curl -s "$API/v1/config/apply" -H "Authorization: Bearer $ORISHARE_SECRET_KEY" \
  -H 'Content-Type: application/json' \
  -d "{\"document\": $(cat config.json), \"mode\": \"preview\", \"expected_revision\": \"$REVISION\"}"

The orishare CLI wraps the same calls (config pull --schema v2, config push); it is a workspace package of the Orishare repository, not published to npm. See Promote between environments.

On this page