Skip to main content

as-engine

The spec-driven engine behind the *-as command-line tools (jira-as, confluence-as).

It reads Atlassian's published OpenAPI documents as Base Documents, applies Enrichment Entries (an OpenAPI Overlay in a small target subset) where the documents are silent or wrong, compiles the Enriched Spec into a compact operation index at build time, and interprets that index at runtime: a Generic Surface that can call any operation by its published name, tag-driven transforms (rich text, paging, prerequisite resolution), a guard that enforces project scope, and progressive-disclosure help. Products stay thin: they hold their Base Documents, overlays, Wrapper Verbs and configuration.

Status: bootstrap (JAS-32). The design is the spec on JAS-31 in the grand-camel-platform tracker; the decisions live on the wayfinder map JAS-6.

Index API

Products build their vendored OpenAPI documents with as_engine.build.compile_product(spec_dir, out_dir). The source directory contains manifest.json; each document entry records its source filename, declared API version (info.version), SHA-256, tier, overlay filenames, and explicitly stripped top-level extensions. The build writes deterministic <id>.index.json files and catalog.json. The supported input format is OpenAPI 3; local component references are resolved without network access.

Overlay targets support dot keys, quoted bracket keys, and nonnegative bracket indexes (including chained brackets). Updates merge objects and append arrays; removals delete the selected element. Targets must exist; add properties by updating their parent object. Filters, wildcards, recursive descent, slices, and copy actions are refused explicitly. Metadata on actions is preserved without enforcement; enrichment validation belongs to the product.

compile_document(document, overlays, normalizers=...) also accepts defect normalization callables, applied after overlays. No vendor defects are patched implicitly. JSON uses sorted keys, fixed separators and one trailing newline. The returned catalog is authoritative; packaging should include its listed indexes and catalog.json, not arbitrary older files in the output directory.

At runtime, load_index(path) returns an OperationIndex whose operations map holds Operation records. ProductIndexes(directory) loads catalog entries marked primary at construction; get(document_id) loads lower tiers on demand.

Discovery imports stay lightweight: importing the surface, output and help modules does not load requests, assistant_skills_lib or jsonschema. Transform implementations load when the registry is first used, and the HTTP stack loads when an HTTP transport is constructed. Table output keeps the shared formatter's simple-table and fallback behavior locally so discovery can render tables without loading the shared package's HTTP dependencies.

Development

Development prerequisites: pip install -e '.[dev]' includes hatchling and build; check local wheel and source builds with python -m build --no-isolation. For Base Document refreshes, install oasdiff 1.31.0: on macOS run curl --fail --location --retry 3 --output oasdiff.tar.gz https://github.com/oasdiff/oasdiff/releases/download/1.31.0/oasdiff_1.31.0_darwin_all.tar.gz; on Linux run curl --fail --location --retry 3 --output oasdiff.tar.gz https://github.com/oasdiff/oasdiff/releases/download/1.31.0/oasdiff_1.31.0_linux_amd64.tar.gz. Then run tar -xzf oasdiff.tar.gz oasdiff and chmod +x oasdiff, and place the binary on PATH (required by the refresh acceptance test), or set OASDIFF=/path/to/oasdiff for the refresh script.

pip install -e ".[dev]"
pytest
ruff check .

Releases are tagged v<version>; a published GitHub release builds the wheel, runs the downstream suites of confluence-as and jira-as against it, and only then publishes to PyPI. This package is never promoted on its own: a product's pinned build carries the core version it was released with (ADR 0013 in grand-camel-platform).

Generic Surface

Surface(ProductIndexes(directory), transport_factory) provides call, search, describe and topics. The factory receives (document_id, OperationIndex) and returns a transport implementing call(operation: Operation, parameters: Mapping[str, Any], body: Any) -> Response. Response carries status, body and headers. HTTP domain exceptions reuse assistant-skills-lib; the product can pass its existing HTTP error mapper. The surface converts failures to SurfaceError, including the operation note. It closes transports that provide close() after each call. A direct Python consumer can keep an HTTPTransport context open for pooled sequential calls.

Parameters are checked before the factory is called: required values, primitive and array/object types, enums and retained bounds. kebab_case maps canonical operation/parameter names to flags. Body fields are JSON-typed when parseable; --field 'spaceId="5"' therefore supplies a string while --field spaceId=5 supplies an integer. Files and stdin must contain JSON. Conflicting dotted paths are refused rather than overwritten. parse_call_flags accepts repeated arrays, JSON arrays or comma-separated arrays, explicit true/false, and --name=value. If a spec parameter collides with body, field, format, validate-body or help, its flag is prefixed --parameter-. Duplicate scalar flags are refused.

Bodies are checked only with validate_body=True or after a 400. The small checker supports local references, required/properties, additionalProperties:false, nullable, enums, primitive types, bounds, arrays and allOf/oneOf/anyOf. Unsupported validation keywords yield explicit diagnostics; format annotations are not assertions. It neither imports jsonschema nor fetches references. Validation reflects the indexed schema, including upstream defects such as overlapping oneOf branches. Schema repair belongs in a product overlay.

HTTPTransport serializes path/query/header/cookie parameters, pools requests, applies timeouts, and retries explicit 429 and all 5xx responses with exponential backoff and numeric/date Retry-After. It never retries a 409 or connection exception. Retries on mutation responses follow the existing product policy. JSON bodies retain their encoding; non-JSON multipart/form-data operations accept object fields with @path file parts. Binary-tagged operations stream to atomic files, return metadata, and allow one same-origin redirect; all cross-origin redirects are refused. Python consumers select destinations with Surface.call(..., output=path). Responder, cassette and simulation modes cover both encodings offline; see the binary and multipart contract. Surface.call(..., all_pages=True, limit=120) follows x-as-paging, returns its merged items array, and reports count=120 through the warning callback; one page is the default and the operation's parameters["limit"] remains page size. Prerequisite aliases resolve exact keys through the declared lookup; version tags inject current+1 or the draft override unless a version is supplied. Conflicting aliases/ids fail before lookup; 409 exits with conflict code 7 and never refreshes or retries. Responder.seed(operation_id, responses) queues copied bodies or Response objects and requests records calls; exhausted seeded queues fail. See transform hooks for the ordered, per-Surface registry and extension contract.

Responder(index, status=200, body=...) implements the identical call interface. An explicit body wins, including null; otherwise forced error statuses produce a message, and successes use a media/schema example or bounded deterministic schema generation. It does not persist state or infer a root from reachable schemas. Without an indexed 200 schema/example it returns null. Generated values are representative, not a guarantee that every arbitrary schema constraint is met.

SimulationStore and Simulation provide an opt-in, stateful transport double for product wrapper tests. It keeps a detached JSON snapshot, a shared copied call log, and only the explicitly documented Confluence operation semantics; unknown operations fail instead of reaching a responder or HTTP. See docs/simulation.md for its seed and CQL subset.

Search and topics visit primary indexes only. Search is case-insensitive over ID, summary, path, tags and x-as-note, with every supplied word required to match. Deprecated operations require include_deprecated=True. Naming a lower-tier operation loads that tier on demand. Describe returns a JSON-ready document (method/path, description, parameters, body outline, response schema and extensions) that describe_markdown renders. All x-as tags and vendor scope tags remain visible. x-as-deprecation/x-as-deprecated replacement metadata overrides the standard OpenAPI deprecated flag; x-as-topic accepts a topic string or list.

Additive index metadata

Old records load unchanged. New projections add fields only when source metadata exists: response_schema for an inline 200 schema (the original response_200 remains the named reference or null), response_example for a media example, deprecated, request_body_required, and request_media_types. Parameters retain explicit style/explode. The original requestBody representation is unchanged. These runtime additions require regenerating the product's packaged indexes through its build hook; there is no runtime Base Document fallback.

See exit codes for the machine-readable failure contract.

Progressive help is provided by as_engine.help: pure document builders for a product template, group/topic pages, operation details and existing enrichment examples, rendered consistently as Markdown or JSON. Descriptions support full=True; topic membership uses only x-as-topic, and x-as-risk is exposed for the product CLI's confirmation policy. See docs/help.md for the tag shapes, character-based token caps and golden regeneration command.

Rich-text tags now connect the shared converters to the Surface: tagged Markdown fields become storage or ADF, and tagged responses render as Markdown with lossless placeholders while retaining metadata. representation= chooses a declared write representation and raw=True returns stored response data; neither option changes vendor query parameters. build_body(..., operation=operation) preserves tagged Markdown fields and reads UTF-8 @file values. Date/duration tags use the scalar parser registry. See rich text for encoding, lookup isolation, CLI integration and the optional final-body validation contract.

Jira consumers can use exact OpenAPI parameter flags alongside kebab aliases. Paging also handles POST body continuation fields, optional token last-page signals, and decimal offsets whose published parameter schema is a string; the responder also decodes serialized JSON examples when the response schema declares a matching object or array. These additions preserve the existing Confluence call and paging contracts.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

as_engine-0.1.1.tar.gz (192.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

as_engine-0.1.1-py3-none-any.whl (117.0 kB view details)

Uploaded Python 3

File details

Details for the file as_engine-0.1.1.tar.gz.

File metadata

  • Download URL: as_engine-0.1.1.tar.gz
  • Upload date:
  • Size: 192.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for as_engine-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b7d4e1a2865268246902f9283b8b990fcf0701fdb3fc25eb6ec9ffeb47f21206
MD5 b464f5e0562e4c90f63fb616c1fb4979
BLAKE2b-256 ad6c50de68d7f6e32b4afa3902a4b85290119ba92d27882499dfde747ff88037

See more details on using hashes here.

Provenance

The following attestation bundles were made for as_engine-0.1.1.tar.gz:

Publisher: publish.yml on grandcamel/as-engine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file as_engine-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: as_engine-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 117.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for as_engine-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1a4488543591bdb3935ea25255dd011e3ab53fce852d7fc6aeeee6aeda1476f3
MD5 353eb717355a2dab533e1b2e26035219
BLAKE2b-256 deb561e510cfe6f76a138f45b740e02c3ae1f99ce357e5e11145214672afe5a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for as_engine-0.1.1-py3-none-any.whl:

Publisher: publish.yml on grandcamel/as-engine

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page