16  Interoperability and Federation

Interchange formats and external service integrations in Quarto-Needs are adapters and projections around the canonical engineering graph. External standards transport and federate requirements without compromising canonical identity or provenance.

16.1 Structured Interchange Formats

16.1.1 ReqIF 1.2

Export the canonical requirements graph to ReqIF (Requirements Interchange Format) for exchange with enterprise tools like IBM DOORS, PTC Integrity, or Polarion:

quarto-needs export --format reqif --output requirements.reqif

The exporter maps typed engineering objects, attributes, and canonical relation families to standard ReqIF SpecObjects, SpecTypes, and SpecRelations.

16.1.2 JSON-LD 1.1

Export the graph as Linked Data preserving semantic relation metadata:

quarto-needs export --format jsonld --output graph.jsonld

The JSON-LD projection uses deterministic IRIs, schema vocabularies, and full context mapping compatible with semantic web tooling.

16.2 Standards-Based Federation: OSLC RM

Quarto-Needs provides a bounded adapter for OSLC Requirements Management (RM): discovery and query are read-only, and a reviewed write path can publish local requirements back under explicit contracts.

pip install 'quarto-needs[oslc]'

The optional dependencies provide JSON-LD, Turtle, and RDF/XML normalization. The public CLI exposes four operations:

  1. Catalog Inspection: Lists Service Provider and nested-catalog URIs without following nested catalogs:

    quarto-needs oslc catalog https://provider.example/oslc/catalog --format json
  2. Service Discovery: Inspects one RM Service Provider, its query capabilities, and advertised Resource Shapes:

    quarto-needs oslc discover https://provider.example/oslc/sp/requirements --format json
  3. Query Capability: Executes a bounded HTTP GET query in the context of an explicit Service Provider (or a configured profile), without recursively crawling members:

    quarto-needs oslc query https://provider.example/oslc/query/requirements \
      --service-provider-uri https://provider.example/oslc/sp/requirements
  4. Reviewed Writes: Builds an oslc-write-plan-v1 from an observation export and sends it only with --apply. Updates require a trusted, bound observation that carries an ETag; creates need an explicit collection URI; deletes must be named explicitly:

    quarto-needs oslc write --observations observations.json --bindings bindings.json \
      --apply --bearer-token-env OSLC_TOKEN

The write path’s eight contracts — staleness, conflict, authored-file placement, atomicity, rollback, optimistic concurrency, authorization and audit — are documented in notes/oslc-remote-writes.md, and every run writes an oslc-write-audit-v1 before any failure propagates.

16.2.1 A worked write plan

The inputs are an observation export and explicit bindings. An observation is the normalized form the federation adapter already produces (ExternalRequirementObservation.to_dict()); a write needs its identity (resourceUri, etag, trustState, digest, fetchedAt) and the reviewable content:

{
  "observations": [
    {
      "identity": {
        "resourceUri": "https://provider.example/oslc/requirements/4711",
        "serviceProviderUri": "https://provider.example/oslc/sp/requirements",
        "digest": "sha256:8a182aa272a00a767dcecc12425cdfdc23abe54c4e1da276cd0aece79dab16c0",
        "fetchedAt": "2026-09-10T12:00:00Z",
        "trustState": "trusted",
        "etag": "\"provider-etag-7\"",
        "lastModified": null
      },
      "title": "Authenticate users",
      "description": "The system shall authenticate users with a passkey.",
      "externalIdentifier": null,
      "attributes": {}
    }
  ]
}

bindings.json is the explicit identity bridge — there is no heuristic matching:

{ "https://provider.example/oslc/requirements/4711": "REQ-1" }

Building the plan sends nothing:

$ quarto-needs oslc write --observations observations.json --bindings bindings.json
OSLC write plan: 1 request(s), 0 skipped (not applied; pass --apply to send)
Plan: .quarto-needs/federation/oslc-write-plan.json
  [PUT] REQ-1 -> https://provider.example/oslc/requirements/4711 If-Match "provider-etag-7"

With --apply --bearer-token-env OSLC_TOKEN, the run stops at the first provider refusal and always writes the audit:

{
  "schema": "oslc-write-audit-v1",
  "completed": true,
  "entries": [
    {
      "uri": "https://provider.example/oslc/requirements/4711",
      "canonicalId": "REQ-1",
      "method": "PUT",
      "ifMatch": "\"provider-etag-7\"",
      "bodyDigest": "sha256:86ef43564d153dc38a28dffa68a2d278e5a205ed9376f5eab55add8dc2cd4aeb",
      "status": 200,
      "responseEtag": "\"provider-etag-8\"",
      "responseLocation": null,
      "error": null
    }
  ]
}

A 412 or 409 records the failing request with status: null and the precondition-failed/conflict code, then stops; a create records the provider’s Location in responseLocation. The observation export itself comes from the federation library surface described below.

The query result reports member URIs, any nodes already inline in the response, and the response’s digest and retrieval timestamp. The CLI does not materialize independent requirement observations or reconcile them with local objects.

Those additional operations are Python library APIs: quarto_needs.oslc_observe.materialize_query_observations() produces external observations with individual provenance, and quarto_needs.oslc_reconcile.reconcile_external_requirements() compares observations with canonical objects using explicit URI-to-ID bindings. They require caller-supplied inputs and do not run implicitly after oslc query.

Credentials are provided securely via environment variables:

export OSLC_TOKEN="..."
quarto-needs oslc discover https://provider.example/oslc/sp/requirements --bearer-token-env OSLC_TOKEN

The command-line reference documents named profiles, cache behavior, retrieval limits, optional shape fetching, and every public OSLC command. It also covers JSON, CSV, SARIF, JUnit, and Markdown exports used by automation.

16.3 External Issue Trackers: GitHub Issues

The Python engine contains a read-only GitHub Issues adapter with bounded retrieval, provenance, conditional caching, reconciliation, and reviewed import/apply primitives. This adapter is a library/engine surface; there is no public quarto-needs github ... CLI command yet. The separate github-report --git BASE..HEAD command prints a projection of local Git changes; it does not retrieve issues.

The adapter:

  • normalizes issues into external observation envelopes;
  • handles pagination and conditional HTTP caching (If-None-Match / 304 Not Modified);
  • treats issue numbers as external data rather than overriding canonical IDs;
  • requires explicit apply review before any local requirement creation.

A dedicated command-line surface is deferred until its user-facing authentication and import workflow can be documented and tested as a stable contract.