Skip to content

Secure and structure runtime-template administration #157

Description

@alexeygrigorev

Status

Groomed and ready for implementation.

Problem

The canonical frontend exposes runtime-template create, edit, and delete controls to every authenticated operator. The backend receives no verified actor context on template routes, so it cannot enforce privileged mutations. Editing is a raw JSON textarea, writes have no concurrency token, deletion does not protect referenced templates, and the current tests do not prove authorization or saved-definition instantiation fidelity.

In this issue, the intended maintainer/admin boundary maps to the existing User.role = admin role. Adding a new maintainer role is out of scope.

Scope

Deliver a server-enforced, admin-only runtime-template administration flow in the canonical frontend and API.

Authorization

  • Route template mutations through the repository's verified server-side actor path. Do not trust role, user ID, or forwarding headers supplied by the browser.
  • POST, PUT, and DELETE are allowed only for an authenticated active admin.
  • Unauthenticated requests return JSON 401; authenticated non-admin requests return JSON 403; neither path mutates data or writes a success audit event.
  • Operators may continue to list/read templates and instantiate workflows when otherwise authorized.
  • Mutation controls are absent from the operator UI, but UI hiding is not the security boundary.
  • Preserve the existing API error envelope and do not leak template contents, user details, or internal authorization data.

Structured editor

Replace the raw-JSON-first form with structured controls for the complete supported runtime-template contract:

  • template metadata: name, type, emoji, tags, and default assignee;
  • trigger settings: type, schedule, lead time, and enabled state;
  • phases and source/reference or bundle links;
  • ordered task definitions, including ref ID, description, day offset, phase, assignee, instructions/document step, systems, validation, proof requirement, required link/file, completion stage, and artifact/assistant/audit references;
  • add, remove, and keyboard-accessible reorder controls with visible focus and validation tied to the relevant field.

JSON may appear only in a collapsed Advanced JSON disclosure. It is a read-only, normalized representation of the structured draft; the primary create/edit path must not require JSON authoring, and supported fields must not be silently discarded.

Save and concurrency states

  • Add a monotonic integer template version. New templates start at 1; successful updates increment it.
  • Existing records without a version are exposed as version 1 and can be upgraded by the first conditional write without an offline data migration.
  • PUT and DELETE require the client's expectedVersion and use a datastore conditional write. Missing or stale versions return JSON 409 conflict; the response may expose the current version and updatedAt, but not a replacement definition.
  • The editor visibly distinguishes clean/saved, dirty, saving, validation error, permission/network error, and conflict states.
  • Prevent duplicate submissions. A failed or conflicting save preserves the local draft. Conflict recovery offers an explicit reload of the server version and never overwrites either version silently.
  • Closing, navigating away from, cancelling, or switching templates with an unsaved draft requires confirmation.

Safe deletion and audit

  • Hard deletion is allowed only when the template has zero references. The server, not the browser, checks all persisted reference classes, including bundles/tasks with templateId and any scheduler or recurrence reference to the template.
  • A referenced template is not deleted and returns JSON 409 template_in_use with sanitized counts/categories only—no private names, descriptions, or IDs. There is no browser force-delete path.
  • The UI uses a destructive confirmation naming the template and explains that referenced templates cannot be deleted.
  • Record privacy-safe immutable audit events for successful create/update/delete mutations and rejected delete attempts. Include actor ID, template ID, action, outcome/reason, prior/result version where applicable, timestamp, and changed field names; do not store the full definition, credentials, document contents, or other sensitive values.
  • A successful mutation and its success audit record must not diverge: use an atomic write when supported or fail closed with a tested compensating strategy.

Saved-definition fidelity

Prove a real round trip through persistence:

  1. An admin creates or edits a template through the structured editor, including multiple reordered tasks and non-default optional fields.
  2. The UI reloads the saved definition from the API.
  3. A workflow is instantiated from that saved definition.
  4. The resulting bundle/tasks preserve the saved task order and supported values, including offsets, phases, descriptions, instructions, proof requirements, milestones/completion stages, assignees, references, required links/files, and bundle/source links.

The test must fail if instantiation uses a stale client draft, fixture, or hard-coded template instead of the saved record.

Acceptance criteria

  • Verified server-side actor resolution protects all template mutation routes; admin succeeds, operator receives 403, unauthenticated receives 401, and spoofed client identity/role headers do not grant access.
  • The canonical UI exposes mutation controls only to admins and uses the structured, accessible, reorderable editor described above.
  • Advanced JSON is secondary/read-only, and a save/reload round trip loses no supported fields.
  • Dirty, saving, saved, validation, permission/network error, and conflict states are observable and preserve user work as specified.
  • Conditional update/delete behavior returns deterministic 409 responses for stale versions; concurrent requests cannot silently overwrite or delete newer data.
  • Referenced templates cannot be deleted; an unreferenced template can be deleted only by an admin with the current version.
  • Audit events are privacy-safe and mutation/audit consistency is covered by tests.
  • A saved structured definition instantiates with exact task order and field fidelity.
  • Architecture review records the authorization boundary, version/conditional-write contract, reference scan policy, audit consistency, and compatibility behavior for versionless rows.
  • Design evidence shows admin and operator states plus clean, dirty, saving, conflict, error, and delete-blocked behavior at desktop (1440x900) and mobile (390x844) widths.
  • Tests and evidence contain no real credentials, private links, contact details, raw operational documents, or sensitive fixture data.

Required tests

Backend/API tests must cover:

  • admin allow and operator/unauthenticated/spoofed-header denial for each of POST, PUT, and DELETE, with denial proven non-mutating;
  • create at version 1, conditional update increment, missing/stale-version 409, and two-writer concurrency with exactly one winner;
  • versionless-record compatibility;
  • referenced-delete 409, stale-delete 409, unreferenced delete success, and sanitized error bodies;
  • audit content/redaction and mutation/audit failure behavior;
  • full schema save/reload and instantiation fidelity.

Canonical browser tests against the real backend must cover:

  • role-based control visibility plus direct API denial for an operator;
  • structured task add/remove/reorder, validation, dirty-navigation confirmation, saving/saved/error states, and a conflict that preserves the draft;
  • referenced-delete refusal and named confirmation for an eligible delete;
  • create/save/reload/instantiate with API assertions for exact task order and values;
  • desktop and mobile evidence for the states listed above.

Run the relevant repository checks, including backend build/unit/integration tests and canonical frontend E2E. Source-marker or static-bundle assertions alone do not satisfy behavioral acceptance.

Out of scope

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Must havebackendBackend/APIbugSomething is brokendesignDesign and UXfrontendFrontend UIportalShared portal shell and UXtestingTests and QAwork-engineDataTasks task execution engine

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions