generated from coulomb/repo-seed
Topaz alignment spike — mapping doc + green e2e example
Closes FLEX-WP-0005 T04. Validates ADR-003's commitment to shape the
standalone core for cheap Topaz adapter work.
Spike output:
- docs/topaz-mapping-spike.md — vocabulary map (subject, group, tenant,
knowledge_base, document, plus parent / owner_team / reader / steward /
member relations), Rego module shape, decision envelope, wire-protocol
ranking (gRPC primary, REST fallback, embedding rejected), schema
restatement recommendation, implications for FLEX-WP-0002 / 0004.
- examples/topaz/ — runnable docker-compose deploying Topaz with the
flex-auth-shaped manifest. seed and probe one-shots cover three
scenarios: alice (steward) allow, bob (group→reader) allow, eve
(outsider) deny. End-to-end green on 2026-05-16:
probe: steward-allow OK (check=true)
probe: reader-allow OK (check=true)
probe: outsider-deny OK (check=false)
probe: all checks passed
Key findings recorded as Implementation Notes in the spike doc:
- Rego input contract bridging (Topaz raw shape ↔ flex-auth canonical
shape) is adapter scope, not core scope.
- Topaz identity objects are a Topaz convention; the adapter
materializes them at directory import time.
- Directory-only permission resolution is sufficient for the common
case; Rego is reserved for context-dependent decisions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
66
examples/topaz/scripts/probe.sh
Executable file
66
examples/topaz/scripts/probe.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
# Probe the Topaz directory's Check API to verify the seeded manifest
|
||||
# correctly resolves reader/steward/outsider permissions for the
|
||||
# Markitect internal-document fixture. Exits 0 if all checks match
|
||||
# expectations.
|
||||
#
|
||||
# This probe deliberately uses the directory Check API rather than the
|
||||
# authorizer Is API. The manifest permissions are the substrate the
|
||||
# Topaz adapter (FLEX-WP-0004 T01) and the standalone evaluator both
|
||||
# consult; demonstrating it works end-to-end here is the spike's actual
|
||||
# validation question. Bridging flex-auth's Rego input shape into
|
||||
# Topaz's raw authorizer input is adapter work, intentionally out of
|
||||
# this spike's scope (see docs/topaz-mapping-spike.md §"Implementation
|
||||
# Notes").
|
||||
|
||||
set -eu
|
||||
|
||||
apk add --no-cache curl jq >/dev/null
|
||||
|
||||
DIR="${DIRECTORY_REST:-http://topaz:9393}"
|
||||
echo "probe: directory REST = $DIR"
|
||||
|
||||
check() {
|
||||
name="$1"
|
||||
subject="$2"
|
||||
resource="$3"
|
||||
permission="$4"
|
||||
expect="$5" # "true" or "false"
|
||||
|
||||
body=$(cat <<EOF
|
||||
{
|
||||
"object_type": "document",
|
||||
"object_id": "$resource",
|
||||
"relation": "$permission",
|
||||
"subject_type": "user",
|
||||
"subject_id": "$subject"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
response=$(curl -sf -X POST "$DIR/api/v3/directory/check" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "$body")
|
||||
|
||||
echo "probe: $name => $response"
|
||||
|
||||
got=$(echo "$response" | jq -r '.check')
|
||||
if [ "$got" = "$expect" ]; then
|
||||
echo "probe: $name OK (check=$got)"
|
||||
else
|
||||
echo "probe: $name FAIL (check=$got; expected=$expect)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Three scenarios on the seeded directory:
|
||||
# 1. Alice is a steward on the document, so read should be permitted.
|
||||
# 2. Bob is a member of reader:platform-architecture, which is the
|
||||
# reader on the document via subject_relation=member, so read should
|
||||
# be permitted via the reader|group#member union in the manifest.
|
||||
# 3. Eve has no relation to the document, so read should be denied.
|
||||
check "steward-allow" "alice@example.test" "document:internal-note" "read" "true"
|
||||
check "reader-allow" "bob@example.test" "document:internal-note" "read" "true"
|
||||
check "outsider-deny" "eve@example.test" "document:internal-note" "read" "false"
|
||||
|
||||
echo "probe: all checks passed"
|
||||
43
examples/topaz/scripts/seed.sh
Executable file
43
examples/topaz/scripts/seed.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
# Seed the Topaz directory: push the manifest, then objects and relations.
|
||||
# Uses Topaz's directory REST gateway. Exits 0 on success.
|
||||
|
||||
set -eu
|
||||
|
||||
apk add --no-cache curl jq >/dev/null
|
||||
|
||||
DIR="${DIRECTORY_REST:-http://topaz:9393}"
|
||||
echo "seed: directory REST = $DIR"
|
||||
|
||||
# 1. Push the directory model (manifest).
|
||||
echo "seed: setting model"
|
||||
curl -sf -X POST "$DIR/api/v3/directory/manifest" \
|
||||
-H 'Content-Type: application/yaml' \
|
||||
--data-binary @/manifest.yaml \
|
||||
|| curl -sf -X POST "$DIR/api/v3/model" \
|
||||
-H 'Content-Type: application/yaml' \
|
||||
--data-binary @/manifest.yaml
|
||||
|
||||
echo
|
||||
|
||||
# 2. Push objects.
|
||||
echo "seed: writing objects"
|
||||
jq -c '.objects[]' /data/objects.json | while IFS= read -r obj; do
|
||||
curl -sf -X POST "$DIR/api/v3/directory/object" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"object\":$obj}" >/dev/null
|
||||
printf '.'
|
||||
done
|
||||
echo
|
||||
|
||||
# 3. Push relations.
|
||||
echo "seed: writing relations"
|
||||
jq -c '.relations[]' /data/relations.json | while IFS= read -r rel; do
|
||||
curl -sf -X POST "$DIR/api/v3/directory/relation" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"relation\":$rel}" >/dev/null
|
||||
printf '.'
|
||||
done
|
||||
echo
|
||||
|
||||
echo "seed: done"
|
||||
Reference in New Issue
Block a user