Append-Only Walkthrough
The first Shape use case is append-only resource protection.

Declare the invariant
Section titled “Declare the invariant”An append-only trait allows appends and reads, then forbids final destructive effects:
module audit
trait AppendOnly<T: Resource> { allow Append<T> allow Read<T> forbid final DropStorage<T> forbid final HardDelete<T> forbid final Truncate<T>}
resource AuditEvent : AppendOnlyfinal matters because a component grant cannot override it. A component may grant HardDelete<AuditEvent>, but the checker still rejects a function that emits it.
Model the safe functions
Section titled “Model the safe functions”module audit
trait AppendOnly<T: Resource> { allow Append<T> allow Read<T> forbid final DropStorage<T> forbid final HardDelete<T> forbid final Truncate<T>}
resource AuditEvent : AppendOnly
component AuditStore { owns AuditEvent grants Append<AuditEvent> grants Read<AuditEvent> fn appendEvent source ts("src/audit/store.ts#appendEvent") effects complete { Append<AuditEvent> evidence ts("src/audit/store.ts:8-14") } fn listEvents source ts("src/audit/store.ts#listEvents") effects complete { Read<AuditEvent> evidence ts("src/audit/store.ts:18-25") }}This model passes because the component grants the emitted effects and the trait does not forbid them.
Add the unsafe function
Section titled “Add the unsafe function”module audit
trait AppendOnly<T: Resource> { allow Append<T> allow Read<T> forbid final DropStorage<T> forbid final HardDelete<T> forbid final Truncate<T>}
resource AuditEvent : AppendOnly
component AuditStore { owns AuditEvent grants Append<AuditEvent> grants HardDelete<AuditEvent> grants Read<AuditEvent> fn purgeOldEvents source ts("src/audit/purge.ts#purgeOldEvents") effects complete { HardDelete<AuditEvent> evidence ts("src/audit/purge.ts:12-16") }}Run:
shp check fixtures/fail/append_only_hard_delete/audit.shapeThe checker reports a forbidden effect and includes the causal trail:
AuditStore.purgeOldEvents emits HardDelete<AuditEvent>AuditEvent has trait AppendOnlyAppendOnly forbids final HardDelete<AuditEvent>That is the product: a compact declaration, a deterministic rejection, and a diagnostic that reviewers can follow.