Project ROUNDTABLE Docs

Government ledger implementation (WS2)

Routes, role helpers, scoping, and audit behavior behind the /gov surface

This page describes how the government ledger is implemented. For instructions aimed at government users, see the government ledger user guide.

The ledger turns separate conversations into a shared, searchable record. It is protected by government session and role checks; it is not an industry-facing directory of internal notes.

Surface map

RoutePurposeMinimum access
/govDashboard counts, recent activity, duplicate-engagement signal.Government read
/gov/organizationsDirectory with command, status, tag, and small-business filters.Government read
/gov/organizations/[id]Profile, submissions, engagement timeline, dialogue notes.Government read
/gov/engagementsLedger with command, type, status, and organization filters.Government read
/gov/engagements/[id]Detail, notes, edit, delete.Government read; write for mutations
/gov/announcementsRead published announcements; publish form for publishers.Government read / publisher
/gov/callsOpen and closed calls; publish form and status toggle for publishers.Government read / publisher
/gov/commandsCommand hierarchy and PAE portfolio browser.Government read
/gov/searchCross-entity search via searchAll.Government read
/gov/notificationsNotification feed and settings.Government read
/gov/admin/users, /gov/admin/commands, /gov/admin/auditAdministration.Admin-tier; audit is Program/System Admin

The /gov layout requires a government session, enforces pending password rotation, and renders navigation conditionally: the Admin item appears only for ADMIN_TIER_ROLES.

Role helpers

Write helpers are intentionally distinct, and a role that passes one does not necessarily pass another. Check the route's helper rather than copying a UI permission:

HelperCoversRoles that pass
requireGovReadAll ledger reads.GOV_READONLY, GOV_POC, GOV_COMMAND_LEAD, GOV_ADMIN, GOV_SYSTEM_ADMIN
requireGovWriteEngagements, notes, organization status, dialogue.GOV_POC, GOV_COMMAND_LEAD, GOV_ADMIN, GOV_SYSTEM_ADMIN
requireGovPublisherAnnouncements and calls.GOV_COMMAND_LEAD, GOV_ADMIN, GOV_SYSTEM_ADMIN
Admin helpersUsers and commands; audit and export are narrower.ADMIN_TIER_ROLES; PROGRAM_ADMIN_ROLES for audit/export; GOV_SYSTEM_ADMIN for hierarchy and admin-role grants

See authentication and roles for scoping examples.

Dashboard

The dashboard aggregates organization count, submissions in the current quarter, total/planned/follow-up/completed engagements, engagements by command, recent submissions and engagements, and a duplicate signal: organizations engaged by more than one command within the past 90 days or upcoming. The duplicate signal is a coordination warning, not a uniqueness constraint — legitimate multi-command work remains possible.

Organizations

PATCH /api/gov/organizations/[id]/status moves an organization between NEW, UNDER_REVIEW, ACTIVE, WATCHLIST, and INACTIVE; the client component applies the change on selection with no separate submit, and surfaces Unable to update status. on failure. POST /api/gov/organizations/[id]/dialogue appends a government-only note (4,000 character cap) recording author, organization, body, and timestamp. Both write audit events.

When reading a profile, keep the surfaces separate — profile facts are organization-provided, submission summaries are industry-provided, match scores are generated by code, engagements are government-entered, dialogue notes are internal context, and audit events record application actions. Conflating them turns an automated match into an apparent endorsement.

Engagements

The engagement route validates the organization and command foreign keys, creates the row, assigns the current government user as createdBy, and audits engagement_created. Notes are appended with POST /api/gov/engagements/[id]/notes and record their own author. Deletion removes the engagement and its notes.

Types: CONFERENCE, TRADE_SHOW, SYMPOSIUM, INDUSTRY_FORUM, TECH_EXERCISE, SITE_VISIT, MEETING, DEMO, OTHER. Statuses: PLANNED, COMPLETED, FOLLOW_UP, CLOSED.

The form disables submission when no organization or command exists, because both are required foreign keys.

Publishing

Calls are created with title (200 characters), description (8,000 characters), normalized lowercase tags (400 characters), and an optional close date; a blank date produces an open-ended call. The route creates an OPEN CallForTechnology, audits the publication, and calls notifyAllIndustry. Industry users then see the call at /portal/calls and may reference it from a submission until it is closed. A status toggle closes and reopens a call without deleting responses.

Announcements follow the same publication pattern with a title and body instead of a deadline. Both require requireGovPublisher; readonly users and POCs receive a role explanation instead of a form.

Commands, portfolios, and hierarchy

The command directory exposes name, abbreviation, echelon, parent, location, and mission. PortfolioNode records provide PAE technical groupings, tags, assigned interest profiles, and routed-submission counts. Administration separates metadata from hierarchy authority:

  • POST /api/gov/admin/commands creates a command.
  • PATCH /api/gov/admin/commands/[id] edits metadata.
  • DELETE /api/gov/admin/commands/[id] removes an eligible command.
  • PATCH /api/gov/admin/commands/[id]/parent reparents after self/cycle checks.

Only GOV_SYSTEM_ADMIN may change the authorization-relevant tree. Reparenting validates the body, rejects self-parenting, walks the proposed parent chain to reject cycles, and updates the row inside a serializable transaction so concurrent changes cannot jointly create a cycle; the previous and new parent IDs are recorded in admin_command_reparent. Other sessions refresh authorization attributes from the database.

Never exercise this flow against a shared production-like tree without an approved change plan: hierarchy is authorization data, not presentation.

User administration and audit

The admin user page lists government users within the caller's scope and creates or updates role, command assignment, and title. Passwords are validated and hashed server-side. Granting or revoking admin-tier roles is reserved for system-admin policy, a caller cannot modify their own account, and the route protects the last system administrator. The audit page is read-only and shows the 200 most recent events (timestamp, event, user, detail) to PROGRAM_ADMIN_ROLES.

Permission failures

Unauthenticated requests return 401. A signed-in industry user receives 403 for government operations. A command lead acting outside its command receives 403 plus an authorization_failure audit record. A Program Admin sees enterprise data but still cannot use system-admin-only hierarchy operations.