4.2 KiB
Topaz Adapter Operations
Status: implemented for FLEX-WP-0004 P4.1.
Role
The Topaz adapter is a delegated PDP and directory adapter behind the
stable flex-auth API. Protected systems still send CheckRequest,
BatchCheckRequest, registry snapshots, and Rego-in-Markdown policy
packages to flex-auth. The adapter translates those into Topaz directory
objects, relations, permission checks, and an OPA bundle, then wraps the
result back into the same DecisionEnvelope used by standalone mode.
Wire Protocol
The production recommendation remains gRPC because it is Topaz's native
API and gives the strongest typed client surface for authorizer,
reader, writer, and model operations. The implementation added in P4.1
keeps that choice behind internal/adapters/topaz.Client and ships an
HTTP REST client for the runnable examples/topaz topology.
This split is deliberate:
Clientis the stable flex-auth boundary.HTTPClientspeaks the same REST endpoints used by the spike (/api/v3/directory/check,/object,/relation,/manifest).- A future gRPC client can replace
HTTPClientwithout changing protected-system contracts or CARING envelope behavior. - Embedded Topaz remains out of scope because it would couple flex-auth releases to Topaz internals.
Startup
- Start Topaz with the manifest and bundle paths mounted. The
examples/topaz/docker-compose.ymlfile is the local reference. - Create a
topaz.HTTPClientwith the directory REST gateway URL. - Configure a
topaz.FileBundleSinkthat points at the mounted bundle directory. - Build a
topaz.Adapterwith the client and policy metadata. - Call
ImportManifest,ImportDirectory, andImportPolicybefore accepting delegated checks.
For local verification:
cd examples/topaz
docker compose up --abort-on-container-exit --exit-code-from probe
The Go integration test is present but skipped by default. Run it with:
FLEX_AUTH_RUN_TOPAZ_INTEGRATION=1 go test ./internal/adapters/topaz
Directory Consistency
ImportDirectory converts the canonical registry snapshot into Topaz
objects and relations. Subjects and service accounts become Topaz
user objects. Each subject also receives an identity:<subject> object
with an identifier relation to the user. Groups and teams become Topaz
group objects; teams keep the team: prefix. Resources keep their
canonical type names, labels, trust zone, path, owner, and system in
properties.
Relation writes return an optional etag. The adapter records the latest
etag in DecisionEnvelope.provenance.directory_etag when Topaz returns
one. Reads may be served from flex-auth's local registry for explanation
or from Topaz for authorization. The decision envelope must say which
backend produced the answer through provenance.evaluator and
provenance.mode.
Policy Import
ImportPolicy extracts the validated Rego module from a
Rego-in-Markdown package without translation. FileBundleSink writes:
.manifestwith the package root.policy/<package/path>.regowith the exact extracted module.
This matches the local-bundle mode used by the Topaz example. Clustered Topaz deployments can replace the bundle sink with a remote bundle publisher without changing the adapter contract.
Fail-Closed Defaults
Delegated checks do not leak backend errors to protected systems as ambiguous success. The adapter returns a deny envelope for:
- Topaz unavailable:
reason=topaz_unavailable. - Stale directory:
reason=topaz_directory_stale. - Partial result:
reason=topaz_partial_result. - Untranslatable request:
reason=topaz_request_incomplete.
Each failure includes a CARING conformance finding and
diagnostics.topaz_failure. This keeps delegated mode behavior
compatible with standalone fail-closed decisions and makes backend
health visible to audits.
CARING Preservation
The adapter preserves CARING descriptors from the request or backend
result. It copies descriptor, restrictions, exposure modes, derived
capabilities, conformance findings, and exposure-event hooks into the
decision envelope. If no descriptor is available, the decision still
contains a TOPAZ-CARING-DESCRIPTOR-MISSING warning so conformance
checks can distinguish an authorization deny from a metadata gap.