Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,13 @@ repository still gets a decision, never by following the link; no release carrie
- :sparkles: feat(examples): thicken service-catalog with nested sla/runtime objects
- :sparkles: feat(examples): thicken topic-registry nested YAML and nested-pointer rules
- :sparkles: feat(examples): thicken infra-vars nested tfvars maps (EX-S04)
- :sparkles: feat(examples): close REF-EX C1-C4 in topic-registry/service-catalog

### Fixes
- :bug: fix(ci): pin ci-audit-test in the AUD-S18 check-stage list
- :bug: specs(p5-ex): make S10 schema freeze and S07 fence non-vacuous
- :bug: fix(docs-gates): fail on unmapped format tokens and de-confound the tests-dir mutation (EX-S01 review)
- :bug: fix(examples): make privilege-tier's proving fixture load-bearing

### Refactoring
- :recycle: refactor(examples): discover dogfood packs instead of a hardcoded 3-name loop
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Privilege-tier allow-list (REF-EX C2) — /services/*/tier already exists on every
# service entry and is already caught by only-safe-fields (any non-/oncall field
# change escalates to require-review, allowed-fields.yaml). This rule adds a
# NARROWER, value-level check on top of that coarse field-level one: a tier value
# outside the allow-list is a privilege-escalation attempt, not just an "other
# field changed" event. Reuses the allowed-fields obligation (already required)
# so no bindings.yaml change is needed. D-061: this stays a scalar leaf check on
# the already-governed keyed-list entry field — no unkeyed nested list is
# reintroduced.
#
# Allow-list is [1, 3], deliberately EXCLUDING 2: tier 2 is a deprecated
# mid-band value being consolidated away (existing tier-2 services, e.g.
# storefront-web in the S02 fixtures, are grandfathered — they simply never
# trigger a tier MODIFY — but no NEW assignment to 2 is permitted). This is
# also what makes the rule's proving polarity load-bearing: a flat [1,2,3]
# allow-list would let the pre-existing S02 allowed-fields/negative golden
# (which coincidentally moves tier 1->2) silently double as this rule's
# proving-polarity witness, so deleting THIS pack's own privilege-tier/
# positive fixture would leave --coverage falsely green. With 2 excluded, that
# S02 fixture's 1->2 change instead becomes a (tolerated, unasserted) FAILING
# firing of this rule — proving-polarity coverage comes ONLY from this pack's
# own privilege-tier/ fixture (tier 1->3).
apiVersion: assent.dev/v1alpha1
kind: MergePolicy
metadata:
name: catalog-privilege-tier
spec:
entries:
catalog-service:
mode: list
root: /services
identity:
pointer: /name
rules:
- name: tier-allow-list
phase: enforce
match:
valueChanges:
pointers: ["/services/*/tier"]
kinds: [modify]
prove:
obligation: allowed-fields
when: "new in [1, 3]"
onFailure:
effect: require-review
code: allowed-fields.tier-out-of-range
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"apiVersion": "catalog/v1",
"services": [
{
"name": "orders-api",
"owner": "orders-team",
"tier": 1,
"oncall": "orders-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
},
{
"name": "payments-gateway",
"owner": "payments-team",
"tier": 1,
"oncall": "payments-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
},
{
"name": "storefront-web",
"owner": "storefront-team",
"tier": 2,
"oncall": "storefront-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# tier 1 -> 3 is within the allow-list ([1,3]) -> tier-allow-list proves silently
# (its proving polarity — and, since 2 is deliberately excluded from the
# allow-list, this fixture is the SOLE source of that proving credit in the
# pack: deleting it genuinely reddens --coverage, see the rule file comment).
# The pre-existing only-safe-fields rule still escalates ANY non-/oncall field
# change to require-review regardless of value — that is unrelated
# coarse-grained coverage, not this rule's finding.
decision: REVIEW
findings:
- rule: only-safe-fields
obligation: allowed-fields
effect: require-review
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
author:
login: alice
groups: [orders-team]
oncall:
orders_rotation: "ready"
schema:
valid: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"apiVersion": "catalog/v1",
"services": [
{
"name": "orders-api",
"owner": "orders-team",
"tier": 3,
"oncall": "orders-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
},
{
"name": "payments-gateway",
"owner": "payments-team",
"tier": 1,
"oncall": "payments-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
},
{
"name": "storefront-web",
"owner": "storefront-team",
"tier": 2,
"oncall": "storefront-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"apiVersion": "catalog/v1",
"services": [
{
"name": "orders-api",
"owner": "orders-team",
"tier": 1,
"oncall": "orders-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
},
{
"name": "payments-gateway",
"owner": "payments-team",
"tier": 1,
"oncall": "payments-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
},
{
"name": "storefront-web",
"owner": "storefront-team",
"tier": 2,
"oncall": "storefront-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# tier 1 -> 0 is outside the allow-list ([1,3]) -> tier-allow-list fails, on top
# of the coarse-grained only-safe-fields escalation (both effects are
# require-review, so the decision stays REVIEW either way).
decision: REVIEW
findings:
- rule: only-safe-fields
obligation: allowed-fields
effect: require-review
- rule: tier-allow-list
obligation: allowed-fields
effect: require-review
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
author:
login: alice
groups: [orders-team]
oncall:
orders_rotation: "ready"
schema:
valid: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"apiVersion": "catalog/v1",
"services": [
{
"name": "orders-api",
"owner": "orders-team",
"tier": 0,
"oncall": "orders-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
},
{
"name": "payments-gateway",
"owner": "payments-team",
"tier": 1,
"oncall": "payments-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
},
{
"name": "storefront-web",
"owner": "storefront-team",
"tier": 2,
"oncall": "storefront-rotation",
"sla": {
"slo_percent": 99.9,
"window": "30d"
},
"runtime": {
"language": "go",
"replicas": 3
}
}
]
}
4 changes: 2 additions & 2 deletions examples/packs/topic-registry/.assent/bindings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ bindings:
environment: dev
packs: [topics]
risk: { threshold: 10 }
require: [ownership, bounded-change, non-destructive, schema-valid]
require: [ownership, bounded-change, non-destructive, schema-valid, wildcard-grant]
- class: kafka-topic
environment: prod
packs: [topics]
risk: { threshold: 4 }
require: [ownership, bounded-change, non-destructive, schema-valid]
require: [ownership, bounded-change, non-destructive, schema-valid, wildcard-grant]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# List-no-shrink (REF-EX C1) — identity-keyed `consumers` map on a topic entry.
# consumers is keyed by consumer name (not an unkeyed list, ADR-0017 §5), so a
# per-key add/delete is a genuine one-sided scalar change the differ can represent
# (E1-S05: a one-sided ADD of a whole new mapping is opaque, but consumers already
# exists as a map on every topic that declares it — only the LEAF key is one-sided).
# Reuses the no-destruction pattern (non-destructive obligation, cf.
# non-destructive.yaml): a consumer key ADD proves (kind != "delete"), a consumer
# key DELETE fails -> require-review. Pointer-scoped to /*/consumers/* so this rule
# is silent (vacuous, no match at all) on every topic file that never declares
# `consumers` — the S02 goldens stay green untouched.
apiVersion: assent.dev/v1alpha1
kind: MergePolicy
metadata:
name: topics-list-no-shrink
spec:
entries:
kafka-topic:
mode: map
root: ""
rules:
- name: consumer-removal
phase: enforce
match:
valueChanges:
pointers: ["/*/consumers/*"]
kinds: [add, delete]
prove:
obligation: non-destructive
when: 'kind != "delete"'
onFailure:
effect: require-review
code: destruction.consumer-removed
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Soft-delete-as-field-add (REF-EX C4) — a topic adding `status: retired` (a field
# base entirely lacked) is a destructive lifecycle transition disguised as an
# innocuous field add, not a silent-APPROVE metadata edit. Reuses the
# non-destructive obligation (cf. non-destructive.yaml / list-no-shrink.yaml):
# matched ONLY on kind add at the dedicated /*/status pointer, so a modify of any
# OTHER field (retention_hours, description, ...) never fires this rule even when
# status is untouched (Edge case in REQ-EX-S06-04) — proven by every existing S02
# golden, none of which declare `status` at all (vacuous, no match). Both
# polarities exercise the SAME add-kind match: adding status as anything other
# than "retired" proves silently; adding it as exactly "retired" fails.
apiVersion: assent.dev/v1alpha1
kind: MergePolicy
metadata:
name: topics-soft-delete
spec:
entries:
kafka-topic:
mode: map
root: ""
rules:
- name: status-retired-add
phase: enforce
match:
valueChanges:
pointers: ["/*/status"]
kinds: [add]
prove:
obligation: non-destructive
when: 'new != "retired"'
onFailure:
effect: require-review
code: destruction.soft-delete
Loading