Adds the risk register as a sibling of MDL under archive/<party>/, and
three project-level virtual aggregations at <project>/{ssr,mdl,rsk}:
- SSR aggregates archive/<party>/ssr.yaml; "+ Add row" materializes a
new party folder (mkdir + auto-own .zddc + ssr.yaml). Renames go
through X-ZDDC-Op: ssr-rename, which os.Rename's the party
directory so every row inside follows. Party name doubles as the
folder name (no opaque IDs) and is path-derived on read.
- MDL/RSK rollups list every deliverable / every risk across all
parties with a derived `party` column; "+ Add row" is suppressed
because party affiliation is ambiguous in the aggregate view.
All four virtual roots are declared `virtual: true` in
defaults.zddc.yaml. Spec/form bytes come from six new embedded
defaults (default-rsk.*, default-ssr.*, default-project-{mdl,rsk}.*)
served via a generalized IsDefaultSpec/IsDefaultSpecAbs that replaces
the MDL-only recognizer. Listing synthesis lives in fs/tree.go;
ACL on each synthetic row evaluates against the canonical
archive/<party>/ chain so non-owners see rows read-only. PUT/DELETE
through virtual URLs rewrite to canonical paths in fileapi.go via
sibling-shape blocks that don't touch the ACL gate. SSR row DELETE
returns 405 (delete the party folder via the archive view).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
83 lines
2.3 KiB
YAML
83 lines
2.3 KiB
YAML
# Default row schema for a Risk Register entry, served by
|
|
# zddc-server when no operator-supplied form.yaml exists at
|
|
# archive/<party>/rsk/.
|
|
#
|
|
# Likelihood and impact use the standard 1-5 ordinal scales;
|
|
# severity is also 1-25 (typically L*I) and stored on each row so
|
|
# operators can override it when the simple product doesn't capture
|
|
# the actual risk profile.
|
|
#
|
|
# To customize: drop your own form.yaml into archive/<party>/rsk/
|
|
# (the same directory as table.yaml). Tighten constraints with
|
|
# `enum:`, `pattern:`, etc. Add fields and they'll appear in the
|
|
# row-edit form; add a matching column to table.yaml to surface
|
|
# the field in the table view too.
|
|
|
|
title: Risk
|
|
description: One identified risk. Likelihood and impact use 1-5 ordinals; severity is stored separately so it can be overridden when L*I underrepresents the residual exposure.
|
|
|
|
schema:
|
|
type: object
|
|
required: [id, title]
|
|
additionalProperties: false
|
|
properties:
|
|
id:
|
|
type: string
|
|
title: ID
|
|
description: Stable identifier, e.g. R-001.
|
|
minLength: 1
|
|
title:
|
|
type: string
|
|
title: Risk
|
|
minLength: 1
|
|
category:
|
|
type: string
|
|
title: Category
|
|
description: Free-form grouping (schedule, cost, technical, regulatory, ...).
|
|
description:
|
|
type: string
|
|
title: Description
|
|
likelihood:
|
|
type: integer
|
|
title: Likelihood
|
|
description: 1 (rare) to 5 (almost certain).
|
|
minimum: 1
|
|
maximum: 5
|
|
impact:
|
|
type: integer
|
|
title: Impact
|
|
description: 1 (negligible) to 5 (catastrophic).
|
|
minimum: 1
|
|
maximum: 5
|
|
severity:
|
|
type: integer
|
|
title: Severity
|
|
description: Residual risk score. Typically likelihood * impact (1-25), but operators can override.
|
|
minimum: 1
|
|
maximum: 25
|
|
mitigation:
|
|
type: string
|
|
title: Mitigation
|
|
description: Plan for reducing this risk's likelihood or impact.
|
|
owner:
|
|
type: string
|
|
title: Owner
|
|
description: Email or party name responsible for tracking this risk.
|
|
status:
|
|
type: string
|
|
title: Status
|
|
enum: [open, mitigated, accepted, closed]
|
|
dueDate:
|
|
type: string
|
|
title: Due date
|
|
format: date
|
|
notes:
|
|
type: string
|
|
title: Notes
|
|
ui:
|
|
description:
|
|
ui:widget: textarea
|
|
mitigation:
|
|
ui:widget: textarea
|
|
notes:
|
|
ui:widget: textarea
|