Work Order System — Electronic Signature Architecture
Classification: Internal — Compliance Engineering Date: 2026-02-13 Status: Proposed Regulatory Mapping: FDA 21 CFR Part 11 §11.50, §11.70, §11.100, §11.200
1. Regulatory Requirements Mapping
1.1 Part 11 Subpart C — Electronic Signatures
| Section | Requirement | Implementation |
|---|---|---|
| §11.50 | Signature manifestations: signed name, date/time, meaning | ElectronicSignature.signerId → Person.name, .signedAt, .meaning |
| §11.70 | Signature/record linking: signatures bound to their respective records | Approval.signatureId FK → ElectronicSignature.id, immutable after creation |
| §11.100 | General requirements: each signature unique to one individual, verified identity before establishment | Person.email unique per tenant, identity verification via IdP/SSO, signature cannot be reused across approvals |
| §11.200 | Electronic signature components: at least two distinct identification components (e.g., ID + password) | ElectronicSignature.authMethod captures authentication context; re-authentication required for each signing event |
1.2 Part 11 Subpart B — Electronic Records
| Section | Requirement | Implementation |
|---|---|---|
| §11.10(a) | Validation of systems | CODITECT platform IQ/OQ/PQ documentation |
| §11.10(b) | Generate accurate and complete copies | Audit trail export with full signature chain |
| §11.10(c) | Protection of records throughout retention period | PostgreSQL with encrypted storage, backup policy |
| §11.10(e) | Audit trail: computer-generated, stamped, independent of operator | AuditTrail table with DB trigger preventing modification |
| §11.10(g) | Authority checks: only authorized individuals can use system | RBAC enforcement at API gateway + state machine guards |
| §11.10(k) | Controls for systems documentation | Version-controlled schema migrations |
2. Signature Flow Architecture
2.1 Sequence Diagram
User Frontend API Gateway WO Service Signature Service PostgreSQL
│ │ │ │ │ │
│ Click "Approve WO" │ │ │ │ │
│───────────────────────>│ │ │ │ │
│ │ │ │ │ │
│ Re-authentication │ │ │ │ │
│ Dialog (password or │ │ │ │ │
│ SSO re-auth prompt) │ │ │ │ │
│<───────────────────────│ │ │ │ │
│ │ │ │ │ │
│ Enter credentials │ │ │ │ │
│───────────────────────>│ │ │ │ │
│ │ POST /signatures │ │ │ │
│ │ {signerId, │ │ │ │
│ │ meaning, │ │ │ │
│ │ authContext} │ │ │ │
│ │───────────────────>│ │ │ │
│ │ │ Validate AuthN │ │ │
│ │ │ + RBAC │ │ │
│ │ │──────────────────>│ │ │
│ │ │ │ Create signature │ │
│ │ │ │──────────────────>│ │
│ │ │ │ │ BEGIN TX │
│ │ │ │ │──────────────────>│
│ │ │ │ │ INSERT signature │
│ │ │ │ │──────────────────>│
│ │ │ │ │ signatureId │
│ │ │ │ │<──────────────────│
│ │ │ │ signatureId │ │
│ │ │ │<──────────────────│ │
│ │ signatureId │ │ │ │
│ │<───────────────────│ │ │ │
│ │ │ │ │ │
│ │ POST /work-orders/{id}/approvals │ │ │
│ │ {role, decision, │ │ │ │
│ │ comment, │ │ │ │
│ │ signatureId} │ │ │ │
│ │───────────────────>│ │ │ │
│ │ │──────────────────>│ │ │
│ │ │ │ Verify: │ │
│ │ │ │ 1. sig.signerId │ │
│ │ │ │ == approverId │ │
│ │ │ │ 2. sig is recent │ │
│ │ │ │ (<5 min) │ │
│ │ │ │ 3. sig not used │ │
│ │ │ │ 4. user has role │ │
│ │ │ │──────────────────────────────────────>│
│ │ │ │ INSERT approval │ │
│ │ │ │ INSERT audit │ │
│ │ │ │ UPDATE wo status │ │
│ │ │ │ COMMIT TX │ │
│ │ │ │<──────────────────────────────────────│
│ │ 200 OK │ │ │ │
│ │<───────────────────│ │ │ │
│ Approval confirmed │ │ │ │ │
│<───────────────────────│ │ │ │ │
2.2 Two-Phase Commit Pattern
The signature flow uses a two-phase pattern to maintain separation of concerns:
Phase 1: Create Signature — Captures identity assertion independent of what is being signed. This mirrors how physical signatures work: the act of signing is separate from what's on the document.
Phase 2: Bind Signature to Action — Associates the signature with a specific approval record on a specific work order. The binding is validated server-side to prevent signature reuse.
This separation enables:
- Signature reuse prevention (each signature ID used exactly once)
- Time-window enforcement (signature must be used within 5 minutes)
- Clear audit trail (signature event and approval event logged separately)
- Support for multi-signature workflows (System Owner + QA on regulatory WOs)
3. Data Model
3.1 ElectronicSignature Entity
interface ElectronicSignature {
id: string; // cuid, immutable
tenantId: string; // RLS partition key
signerId: string; // FK → Person.id (unique individual)
meaning: string; // Human-readable: "Approval of Work Order WO-2026-001"
signedAt: Date; // Server-generated, not client-supplied
reason: string | null; // Optional: why this signature was applied
authMethod: AuthMethod; // How identity was verified
sessionId: string | null; // IdP session identifier
ipAddress: string | null; // Client IP for forensics
consumed: boolean; // True after binding to an approval
consumedAt: Date | null; // When the signature was consumed
consumedBy: string | null; // Which approval consumed it
}
type AuthMethod =
| 'password' // Username + password re-entry
| 'smartcard' // PKI smart card
| 'sso_reauth' // SSO provider re-authentication
| 'biometric' // Fingerprint, face
| 'totp' // Time-based OTP
;
3.2 Approval Entity (Extended)
interface Approval {
id: string;
tenantId: string;
workOrderId: string;
role: 'SYSTEM_OWNER' | 'QA' | 'OTHER';
approverId: string; // FK → Person.id (MUST be human)
decision: 'APPROVED' | 'REJECTED';
decisionTs: Date;
comment: string | null;
signatureId: string; // FK → ElectronicSignature.id (required for Part 11)
// Part 11 manifestation fields (denormalized for report generation)
signerName: string; // Snapshot of Person.name at signing time
signatureMeaning: string; // Copy of signature.meaning
}
3.3 Validation Rules
async function validateSignatureBinding(
signature: ElectronicSignature,
approval: { approverId: string; workOrderId: string }
): Promise<ValidationResult> {
const errors: string[] = [];
// Rule 1: Signer must match approver
if (signature.signerId !== approval.approverId) {
errors.push('Signature signer does not match approver identity');
}
// Rule 2: Signature must be recent (5-minute window)
const ageMs = Date.now() - signature.signedAt.getTime();
if (ageMs > 5 * 60 * 1000) {
errors.push(`Signature expired: ${Math.round(ageMs / 1000)}s old, max 300s`);
}
// Rule 3: Signature not already consumed
if (signature.consumed) {
errors.push(`Signature already consumed by approval ${signature.consumedBy}`);
}
// Rule 4: Signature tenant matches approval tenant
// (Enforced by RLS, but belt-and-suspenders)
return {
valid: errors.length === 0,
errors
};
}
4. Multi-Signature Workflows
4.1 Regulatory Work Order Approval Chain
Regulatory WOs (regulatoryFlag=true) require a two-signature approval:
┌─────────────────────┐
│ PENDING_REVIEW │
└─────────┬───────────┘
│
┌─────────▼───────────┐
│ System Owner │
│ Approval Required │
│ ┌──────────────┐ │
│ │ e-Signature │ │
│ │ Phase 1 + 2 │ │
│ └──────────────┘ │
└─────────┬───────────┘
│
┌─────────▼───────────┐
│ QA Approval │
│ Required │
│ ┌──────────────┐ │
│ │ e-Signature │ │
│ │ Phase 1 + 2 │ │
│ └──────────────┘ │
└─────────┬───────────┘
│
┌─────────▼───────────┐
│ APPROVED │
└─────────────────────┘
4.2 Non-Regulatory Approval Chain
Non-regulatory WOs require only System Owner approval:
PENDING_REVIEW → System Owner e-Signature → APPROVED
4.3 Guard Logic
function getRequiredApprovals(wo: WorkOrder): ApprovalRequirement[] {
const required: ApprovalRequirement[] = [
{ role: 'SYSTEM_OWNER', signatureRequired: true }
];
if (wo.regulatoryFlag) {
required.push({ role: 'QA', signatureRequired: true });
}
// Tenant-configurable additional approvers
const tenantConfig = getTenantApprovalConfig(wo.tenantId);
if (tenantConfig.additionalApprovers) {
required.push(...tenantConfig.additionalApprovers);
}
return required;
}
function canTransitionToApproved(wo: WorkOrder, approvals: Approval[]): boolean {
const required = getRequiredApprovals(wo);
return required.every(req =>
approvals.some(a =>
a.role === req.role &&
a.decision === 'APPROVED' &&
(!req.signatureRequired || a.signatureId != null)
)
);
}
5. Agent-Delegated Signatures
5.1 The Problem
CODITECT agents (QAReviewNode, WorkOrderOrchestratorNode) may need to process approvals, but Part 11 requires signatures from identified individuals. Agents cannot sign.
5.2 Solution: Pre-Authorized Delegation
Human QA Officer QA Review Agent
│ │
│ Pre-authorize: "Approve WO-001 │
│ if all validation artifacts present │
│ and no critical findings" │
│─────────────────────────────────────>│
│ │
│ e-Sign delegation authorization │
│ (Phase 1 signature on the │
│ delegation intent) │
│─────────────────────────────────────>│
│ │
│ Agent verifies conditions:
│ ✓ IQ/OQ docs attached
│ ✓ No critical findings
│ ✓ All child WOs complete
│ │
│ Agent creates approval:
│ approverId = QA Officer
│ signatureId = delegation sig
│ performerType = AGENT
│ agentSessionId = trace-123
│ │
│ Notification: WO-001 approved │
│ on your behalf by QA Review Agent │
│<─────────────────────────────────────│
5.3 Delegation Constraints
| Constraint | Value | Rationale |
|---|---|---|
| Delegation TTL | 24 hours max | Prevent stale authorizations |
| Scope | Single WO or WO batch | No blanket delegations |
| Conditions | Must be machine-verifiable | Agent can't interpret subjective criteria |
| Notification | Mandatory post-action | Human must be informed of agent actions |
| Revocation | Immediate, any time | Human can cancel delegation |
| Audit | Full chain recorded | Delegation → conditions check → approval logged |
6. API Endpoints
6.1 Signature Lifecycle
POST /api/v1/signatures
Request:
signerId: string # Must match authenticated user
meaning: string # "Approval of Work Order {woId}"
reason?: string
authContext:
method: string # "password" | "sso_reauth" | ...
sessionId?: string
Response: 201
id: string
signedAt: string (ISO 8601)
consumed: false
GET /api/v1/signatures/{id}
Response: 200
# Full signature record
POST /api/v1/signatures/{id}/verify
# Internal endpoint for binding validation
Request:
expectedSignerId: string
maxAgeSeconds?: number # Default 300
Response: 200
valid: boolean
errors?: string[]
6.2 Approval with Signature
POST /api/v1/work-orders/{woId}/approvals
Request:
role: "SYSTEM_OWNER" | "QA" | "OTHER"
decision: "APPROVED" | "REJECTED"
comment?: string
signatureId: string # Required for Part 11 transitions
Response: 201
id: string
# Approval record with denormalized signature manifestation
GET /api/v1/work-orders/{woId}/approval-status
Response: 200
required: ApprovalRequirement[]
received: Approval[]
complete: boolean # All required approvals received
canTransition: boolean
7. Audit Trail Integration
Every signature and approval operation generates audit events:
| Action | Entity Type | Captured Data |
|---|---|---|
SIGNATURE_CREATED | SIGNATURE | signerId, meaning, authMethod |
SIGNATURE_CONSUMED | SIGNATURE | consumedBy (approval ID) |
SIGNATURE_EXPIRED | SIGNATURE | expiration reason |
APPROVAL_CREATED | APPROVAL | role, decision, signatureId |
APPROVAL_REJECTED | APPROVAL | role, reason, signatureId |
DELEGATION_CREATED | DELEGATION | delegator, agent, conditions, TTL |
DELEGATION_EXERCISED | DELEGATION | conditions verified, approval created |
DELEGATION_REVOKED | DELEGATION | revoked by, reason |
All events include: tenantId, performedBy, performerType, agentSessionId (if agent), correlationId, performedAt (server timestamp).
8. CODITECT Platform Integration
8.1 Compliance Engine Interception
The CODITECT Compliance Engine intercepts all signature and approval operations:
// Compliance Engine middleware
async function complianceGate(
operation: 'CREATE_SIGNATURE' | 'CREATE_APPROVAL' | 'TRANSITION',
context: OperationContext
): Promise<ComplianceResult> {
// Check 1: Is the signer/approver authorized for this tenant?
await verifyTenantAuthorization(context);
// Check 2: Does the WO's compliance class require additional controls?
if (context.wo.complianceClass === 'FDA_21CFR11') {
await enforcePart11Controls(context);
}
// Check 3: Log to immutable audit trail
await writeAuditEvent(context);
// Check 4: Emit compliance event to Event Bus
await emitComplianceEvent(context);
return { allowed: true };
}
8.2 Event Bus Events
// NATS topics for signature/approval events
const topics = {
signatureCreated: 'wo.compliance.signature.created',
signatureConsumed: 'wo.compliance.signature.consumed',
approvalCreated: 'wo.compliance.approval.created',
approvalChainComplete: 'wo.compliance.approval.chain_complete',
delegationCreated: 'wo.compliance.delegation.created',
delegationExercised: 'wo.compliance.delegation.exercised',
};
8.3 Observability
# Prometheus metrics for signature operations
wo_signature_created_total:
labels: [tenant_id, auth_method]
wo_signature_consumed_total:
labels: [tenant_id]
wo_signature_expired_total:
labels: [tenant_id, reason]
wo_approval_decision_total:
labels: [tenant_id, role, decision]
wo_approval_chain_duration_seconds:
labels: [tenant_id, regulatory_flag]
# Histogram: time from first approval to chain completion
wo_delegation_exercised_total:
labels: [tenant_id, agent_type]
Copyright 2026 AZ1.AI Inc. All rights reserved. Developer: Hal Casteel, CEO/CTO Product: CODITECT-BIO-QMS | Part of the CODITECT Product Suite Classification: Internal - Confidential