FlightOS Instructional Governance Contract
Purpose
This document defines the minimum shared rgp API contract required for FlightOS instructional workflows to move from request-level authority to true stage-level shared governance.
The goal is to let FlightOS:
- submit governed instructional review requests into
rgp - read stage-aware workflow state from
rgp - send reviewer decisions into
rgp - keep CMS UI presentation local without retaining a second workflow engine
Problem Statement
FlightOS instructional workflows currently expose a stage-based CMS review model with:
- ordered review stages
- stage-level approve or request-changes actions
- current-stage tracking
- release gating based on workflow state
rgp currently exposes request-level lifecycle state such as:
under_reviewchanges_requestedapprovedpromotion_pendingpromotedcompleted
That is sufficient for request authority, but not sufficient to drive FlightOS stage-based CMS review UX honestly.
Non-Negotiable Rules
rgpremains authoritative for workflow runtime and reviewer decision state.- FlightOS may project and render workflow state, but shall not persist standalone shared-governance stage state.
- FlightOS may compute product-specific release-safety views locally, but those views must be reproducible from shared request and projection data.
- Shared mode must not silently fall back to FlightOS-local stage mutation.
Scope
This contract is limited to FlightOS instructional workflows backed by:
tmpl_assessment@1.4.0tmpl_curriculum@3.1.0
It does not define a general-purpose stage engine for every rgp request type. It defines a shared governance projection and command surface for the instructional review flow FlightOS already exposes.
Canonical Identity
Every FlightOS instructional request submitted to rgp must include:
{
"input_payload": {
"flightos_content_entry_id": "entry-assessment-grade5-fractions-checkpoint"
}
}
Optional but recommended linkage fields:
{
"input_payload": {
"flightos_content_entry_id": "entry-course-grade5-fractions",
"flightos_schema_id": "course",
"flightos_actor_user_id": "user-42"
}
}
flightos_content_entry_id is the required join key for FlightOS workflow projection.
Shared Projection Model
Add the following models in rgp:
InstructionalWorkflowStageRecordInstructionalWorkflowProjectionRecordInstructionalWorkflowProjectionListResponseInstructionalWorkflowDecisionRequest
Recommended file:
/Volumes/data/development/rgp/apps/api/app/models/governance.py
InstructionalWorkflowStageRecord
{
"stage_id": "INSTRUCTIONAL_DESIGN_REVIEW",
"label": "Instructional Design Review",
"status": "PENDING",
"required": true,
"sequence": 1,
"decision": null,
"decided_at": null,
"decided_by_user_id": null,
"notes": null
}
Fields:
stage_id: enumlabel: stringstatus:PENDING | ACTIVE | APPROVED | CHANGES_REQUESTED | SKIPPEDrequired: booleansequence: integerdecision:APPROVE | REQUEST_CHANGES | nulldecided_at: ISO timestamp or nulldecided_by_user_id: string or nullnotes: string or null
InstructionalWorkflowProjectionRecord
{
"request_id": "req_200",
"tenant_id": "cms-platform",
"flightos_content_entry_id": "entry-assessment-grade5-fractions-checkpoint",
"flightos_schema_id": "assessment",
"template_id": "tmpl_assessment",
"template_version": "1.4.0",
"title": "Assessment Revision: Grade 5 Fractions Checkpoint",
"request_status": "under_review",
"workflow_status": "IN_REVIEW",
"content_kind": "ASSESSMENT",
"current_stage_id": "SME_REVIEW",
"submitted_at": "2026-04-09T16:00:00.000Z",
"submitted_by_user_id": "user-42",
"approved_for_release_at": null,
"released_at": null,
"stages": []
}
Fields:
request_id: sharedrgprequest idtenant_id: tenant idflightos_content_entry_id: required join keyflightos_schema_id:course | assessment | nulltemplate_id: request template idtemplate_version: request template versiontitle: workflow titlerequest_status: rawrgprequest statusworkflow_status: FlightOS-compatible normalized statusNOT_SUBMITTEDIN_REVIEWCHANGES_REQUESTEDAPPROVED_FOR_RELEASERELEASED
content_kind:CURRICULUM_COURSE | ASSESSMENTcurrent_stage_id: stage enum or nullsubmitted_at: ISO timestamp or nullsubmitted_by_user_id: string or nullapproved_for_release_at: ISO timestamp or nullreleased_at: ISO timestamp or nullstages: ordered array ofInstructionalWorkflowStageRecord
InstructionalWorkflowProjectionListResponse
Use standard paginated list format:
{
"items": [],
"page": 1,
"page_size": 25,
"total_count": 1,
"total_pages": 1
}
Stage Definitions
Assessment
Ordered stages:
INSTRUCTIONAL_DESIGN_REVIEWSME_REVIEWASSESSMENT_REVIEWCERTIFICATION_COMPLIANCE_REVIEW
Curriculum
Ordered stages:
INSTRUCTIONAL_DESIGN_REVIEWSME_REVIEWCERTIFICATION_COMPLIANCE_REVIEW
These stage definitions should be derived from template-specific instructional governance rules in rgp, not from FlightOS-local runtime state.
Read Endpoints
Recommended file:
/Volumes/data/development/rgp/apps/api/app/api/v1/endpoints/requests.py
List instructional workflow projections
GET /api/v1/requests/instructional-workflows
Query params:
pagepage_sizeflightos_content_entry_idtemplate_idworkflow_status
Response:
PaginatedResponse[InstructionalWorkflowProjectionRecord]
Behavior:
- filters to instructional templates only
- returns stage-aware workflow projection records
- supports FlightOS list and summary read models
Get instructional workflow projection by request id
GET /api/v1/requests/{request_id}/instructional-workflow
Response:
InstructionalWorkflowProjectionRecord
Optional convenience read by content entry id
GET /api/v1/requests/instructional-workflows/by-content-entry/{flightos_content_entry_id}
Response:
InstructionalWorkflowProjectionRecord
This is optional. FlightOS can work with the list endpoint if the join key is queryable.
Decision Command Endpoint
Recommended file:
/Volumes/data/development/rgp/apps/api/app/api/v1/endpoints/requests.py
Request body
{
"stage_id": "SME_REVIEW",
"decision": "APPROVE",
"notes": "Ready for compliance review."
}
Model:
{
"stage_id": "INSTRUCTIONAL_DESIGN_REVIEW | SME_REVIEW | ASSESSMENT_REVIEW | CERTIFICATION_COMPLIANCE_REVIEW",
"decision": "APPROVE | REQUEST_CHANGES",
"notes": "optional string"
}
Endpoint
POST /api/v1/requests/{request_id}/instructional-workflow/decisions
Response:
InstructionalWorkflowProjectionRecord
Behavior:
- validates that the request is an instructional request type
- validates that the submitted
stage_idmatches the currently active stage - records the decision with actor and timestamp
- advances the next required stage on
APPROVE - moves the workflow to
CHANGES_REQUESTEDonREQUEST_CHANGES - updates underlying request lifecycle state consistently
Required Request Lifecycle Mapping
The projection should map request lifecycle state into FlightOS workflow state as follows.
| RGP request status | FlightOS workflow status |
|---|---|
draft |
NOT_SUBMITTED |
submitted |
IN_REVIEW |
validated |
IN_REVIEW |
classified |
IN_REVIEW |
ownership_resolved |
IN_REVIEW |
planned |
IN_REVIEW |
queued |
IN_REVIEW |
in_execution |
IN_REVIEW |
awaiting_review |
IN_REVIEW |
under_review |
IN_REVIEW |
changes_requested |
CHANGES_REQUESTED |
approved |
APPROVED_FOR_RELEASE |
promotion_pending |
APPROVED_FOR_RELEASE |
promoted |
RELEASED |
completed |
RELEASED |
failed |
CHANGES_REQUESTED |
rejected |
CHANGES_REQUESTED |
Repository and Service Changes In rgp
Add projection and decision models
File:
/Volumes/data/development/rgp/apps/api/app/models/governance.py
Add:
- stage enums reused or mirrored for instructional workflow projection
InstructionalWorkflowStageRecordInstructionalWorkflowProjectionRecordInstructionalWorkflowDecisionRequest
Add endpoint handlers
File:
/Volumes/data/development/rgp/apps/api/app/api/v1/endpoints/requests.py
Add:
- list projection route
- detail projection route
- decision command route
Add service methods
File:
/Volumes/data/development/rgp/apps/api/app/services/request_service.py
Add:
get_instructional_workflow_projection(...)list_instructional_workflow_projections(...)decide_instructional_workflow_stage(...)
Add persistence and transition logic
File:
/Volumes/data/development/rgp/apps/api/app/repositories/governance_repository.py
Add:
- instructional stage projection builder
- request-to-stage mapping logic for
tmpl_assessmentandtmpl_curriculum - stage-decision mutation logic
- transition side effects that keep request lifecycle and stage projection aligned
Validate state transitions
File:
/Volumes/data/development/rgp/apps/api/app/domain/state_machine.py
Likely no new top-level request statuses are required. The missing piece is stage projection and decision handling layered on top of existing request states.
FlightOS Integration Target
Once the rgp contract above exists, FlightOS should update:
/Volumes/data/development/FlightOS/FlightOS/apps/api-server/src/platform/flightosRgpGateway.ts/Volumes/data/development/FlightOS/FlightOS/apps/api-server/src/server.ts
Replace:
- current request-status overlay logic
- current shared-mode
409block on stage decisions
With:
- reads from instructional workflow projection endpoints
- stage decision command to
POST /api/v1/requests/{request_id}/instructional-workflow/decisions
Acceptance Criteria
- FlightOS instructional workflow detail can be rendered entirely from shared
rgpprojection data plus local release-safety computation. - FlightOS instructional workflow list and summary no longer infer stage state from coarse request status alone.
- Shared mode stage decisions no longer call FlightOS-local
decideStage. - A reviewer decision in FlightOS mutates shared
rgpstate and is visible immediately through the projection read API. - The contract works for both
tmpl_assessmentandtmpl_curriculum.