FlowNote FastAPI 서버는 SQLite 기반 현재 REST API를 제공한다. 운영 기본 경로는 /api/v1이며, 파일은 서버 로컬 storage/에 저장한다. 보호 API는 Bearer access token과 auth_sessions 상태를 함께 검증한다.
이 목록은 2026-08-15 현재 OpenAPI에 등록된 163개 method/path 조합 기준이다. 외부 AI API는 provider 중립 adapter와 기본 비활성 안전장치·운영 제어·감사 경계를 제공하지만 실제 AI 사용자 기능의 완료 판정에는 포함하지 않는다. 네트워크 adapter는 test 환경의 별도 명시 설정에서만 생성되며 운영 기본값은 비활성이다. controlled copy와 Android secure view는 서버에 저장된 현재 공개 버전만 각 계약에 따라 1회 스트리밍한다.
운영 설치와 점검은 서버 설치·운영 매뉴얼, 장애 대응은 공통 장애 대응을 따른다.
공개 소스를 처음 실행할 때는 처음 실행하기에 따라 Git 제외 .env와 무작위 비밀값을 만든다. 예제 설정만 복사한 빈 DB는 초기 관리자 비밀번호가 없어 시작을 거부한다.
| Method | Path | Purpose |
|---|---|---|
| GET | / |
Service and environment check |
| GET | /api/v1/health |
Health check |
| GET | /api/v1/health/db |
Database health check |
| GET | /api/v1/health/sync-manifest |
Database health and server instance/epoch/contract manifest |
| GET | /api/v1/sync/manifest |
Server instance/epoch/contract and notification high-water cursor |
| POST | /api/v1/sync/reconciliation-runs |
Classify a WPF queue inventory for administrator review |
| GET | /api/v1/sync/reconciliation-runs/{run_id} |
Read a reconciliation run and all item verdicts |
| POST | /api/v1/sync/reconciliation-runs/{run_id}/apply |
Approve every proposed action and close the run |
| POST | /api/v1/sync/server-epoch/increment |
Increment the explicit server recovery epoch with audit history |
| POST | /api/v1/auth/login |
Login and token issue |
| POST | /api/v1/auth/refresh |
Refresh token rotation |
| POST | /api/v1/auth/logout |
Revoke current session |
| GET | /api/v1/auth/me |
Current user lookup |
| POST | /api/v1/auth/change-password |
Required/self password change and session revocation |
| GET | /api/v1/audit-events |
Read common mutation envelopes and legacy activity history with explicit missing fields |
| GET | /api/v1/change-history |
Rebuildable, permission-filtered integrated change history and action items |
| GET | /api/v1/change-history/{event_id} |
Permission-filtered source audit and current target detail |
| GET | /api/v1/operational-readiness |
Permission-filtered current operational readiness areas and snapshot-cursor action list |
| GET | /api/v1/operational-readiness/{item_id} |
Recomputed readiness action detail with the same scope rules |
| GET | /api/v1/server-accounts |
Server account list |
| POST | /api/v1/server-accounts |
Create server account with one-time temporary password input |
| PATCH | /api/v1/server-accounts/{user_id} |
Change display name, role, or status |
| POST | /api/v1/server-accounts/{user_id}/password-reset |
Reset temporary password and revoke sessions |
| GET | /api/v1/server-accounts/{user_id}/sessions |
Active account sessions |
| POST | /api/v1/server-accounts/{user_id}/sessions/revoke |
Revoke active account sessions |
| POST | /api/v1/server-accounts/{user_id}/sessions/{session_id}/revoke |
Revoke one account session |
| GET | /api/v1/terminal-devices |
Approved terminal device list |
| POST | /api/v1/terminal-devices |
Register approved terminal device |
| GET | /api/v1/terminal-devices/{device_id} |
Terminal device detail |
| GET | /api/v1/terminal-devices/{device_id}/last-seen |
Terminal device last successful login |
| PATCH | /api/v1/terminal-devices/{device_id} |
Update terminal device metadata |
| PATCH | /api/v1/terminal-devices/{device_id}/status |
Change terminal device status |
| POST | /api/v1/terminal-devices/{device_id}/replace |
Retire and replace terminal device |
| POST | /api/v1/documents |
Register document and first version |
| GET | /api/v1/documents |
Document list |
| GET | /api/v1/documents/published |
Published document list |
| GET | /api/v1/documents/{document_id} |
Document detail |
| GET | /api/v1/documents/{document_id}/published |
Published version |
| PUT | /api/v1/documents/{document_id}/tags |
Merge added/removed tags using base revision, canonical intent hash, and mutation key; legacy full replacement remains compatible |
| PATCH | /api/v1/documents/{document_id}/status |
Change document status with base revision and optional mutation key |
| GET | /api/v1/documents/{document_id}/versions |
Version list |
| POST | /api/v1/documents/{document_id}/versions |
Register new version; optional multipart idempotencyKey returns the existing version on retry |
| PATCH | /api/v1/documents/{document_id}/versions/{version_id}/status |
Change version status |
| POST | /api/v1/documents/{document_id}/versions/{version_id}/publish |
Publish the exact approved version with approval ID, base revision, and optional mutation key |
| DELETE | /api/v1/documents/{document_id} |
Soft-delete a document using its base revision, change reason, and optional mutation key |
| POST | /api/v1/document-approvals |
Request review for the exact latest version, revision, and file hash |
| GET | /api/v1/document-approvals |
List approval work items with document, state, and assignee filters |
| GET | /api/v1/document-approvals/{approval_id} |
Read the approval projection and append-only events |
| POST | /api/v1/document-approvals/{approval_id}/decision |
Approve or reject as the assigned governance reviewer |
| POST | /api/v1/document-approvals/{approval_id}/cancel |
Cancel a pending, approved, or published approval and withdraw unused grants when published |
| POST | /api/v1/documents/{document_id}/versions/{version_id}/controlled-copy |
Issue one-time controlled copy grant for the current published version |
| GET | /api/v1/controlled-copies/{token} |
Stream the session-bound controlled copy once |
| POST | /api/v1/documents/{document_id}/versions/{version_id}/android-view-grants |
Issue an approved-device Android secure view grant |
| GET | /api/v1/android-document-views/{token}/stream |
Stream the device/session-bound Android body once |
| POST | /api/v1/documents/{document_id}/access-logs |
Register access log |
| GET | /api/v1/documents/{document_id}/access-logs |
Access log list |
| GET | /api/v1/tags |
Tag list |
| POST | /api/v1/tags |
Tag create |
| POST | /api/v1/field-comments |
FieldComment create |
| GET | /api/v1/field-comments |
FieldComment manager workbench list with assignee role, signal, channel, document version, due date, and operational filters |
| GET | /api/v1/field-comments/{comment_id} |
FieldComment detail |
| PATCH | /api/v1/field-comments/{comment_id} |
Review/analyze FieldComment |
| POST | /api/v1/field-comments/bulk-review |
Bulk assignment, due date, and review-state update |
| POST | /api/v1/field-comments/bulk-review/preview |
Read-only validation of per-item transitions and failure reasons for up to 200 comments |
| POST | /api/v1/field-comments/bulk-review/execute |
Partial-success bulk review with per-item base revision and mutation receipt |
| GET | /api/v1/field-comments/{comment_id}/audit |
Review audit snapshots with source hash |
| GET | /api/v1/field-comments/{comment_id}/traceability |
FieldComment source, attachments, observed document, work sequence, audit, report-source snapshot, and generated-document traceability |
| GET | /api/v1/field-comments/quality-workbench |
Stale, weak-evidence, and missing-source review workbench |
| GET | /api/v1/field-comments/quality-metrics |
Status, signal, actor, line, error, and report-link quality metrics |
| GET | /api/v1/field-comments/review-dashboard |
Server-authoritative review and overdue counts, owners, next actions, and WPF workbench filters |
| POST | /api/v1/field-comments/{comment_id}/attachments |
Attachment create; optional multipart idempotencyKey returns the existing attachment on retry |
| GET | /api/v1/field-comments/{comment_id}/attachments |
Attachment list |
| GET | /api/v1/documents/{document_id}/field-comments |
FieldComments by document |
| POST | /api/v1/work-sequence-boards |
Create board with required idempotencyKey |
| GET | /api/v1/work-sequence-boards |
List boards with optional lineCode and status filters |
| GET | /api/v1/work-sequence-boards/{board_id} |
Board snapshot with ordered items and board_revision |
| POST | /api/v1/work-sequence-boards/{board_id}/items |
Add item with mutation key and base board revision |
| PUT | /api/v1/work-sequence-boards/{board_id}/items/order |
Reorder the complete item set with mutation key and base revision |
| PATCH | /api/v1/work-sequence-boards/{board_id}/items/{item_id}/status |
Change item status/hold reason with mutation key and base revision; HOLD requires a non-blank holdReason or changeReason |
| GET | /api/v1/work-sequence-boards/{board_id}/history |
Change history with mutation key and applied revision |
| GET | /api/v1/work-sequence-boards/{board_id}/notification-candidates |
Notification candidates |
| PATCH | /api/v1/work-sequence-boards/{board_id}/notification-candidates/{candidate_id} |
Change notification candidate status |
| GET | /api/v1/work-sequence-boards/{board_id}/notification-candidates/{candidate_id}/delivery-preview |
Revalidate candidate revision, channel-manager role, active recipients, source, and current published document |
| POST | /api/v1/work-sequence-boards/{board_id}/notification-candidates/{candidate_id}/deliveries |
Persist a channel or handover delivery with candidate-channel and recipient receipts |
| GET | /api/v1/work-sequence-delivery-templates |
List active delivery templates in the current site scope |
| POST | /api/v1/work-sequence-delivery-templates |
Create a site-scoped delivery template |
| PATCH | /api/v1/work-sequence-delivery-templates/{template_id} |
Update or archive a same-site delivery template |
| GET | /api/v1/work-sequence-field-boards |
List work-sequence boards visible to the approved Android device session |
| GET | /api/v1/work-sequence-field-boards/by-item/{item_id} |
Read the visible board snapshot for a channel-linked item |
| GET | /api/v1/work-sequence-field-boards/{board_id} |
Read a visible board snapshot with published-document and allowed-channel references |
| POST | /api/v1/notification-channels |
Create notification channel |
| GET | /api/v1/notification-channels |
List channels visible to current user |
| GET | /api/v1/notification-channels/{channel_id} |
Channel detail |
| POST | /api/v1/notification-channels/{channel_id}/members |
Add or reactivate channel member |
| GET | /api/v1/notification-channels/{channel_id}/members |
Channel member list |
| PATCH | /api/v1/notification-channels/{channel_id}/members/{member_id} |
Change member role or status |
| POST | /api/v1/notification-channels/{channel_id}/messages |
Create channel message; a repeated FIELD_COMMENT_EVENT for the same channel and FieldComment returns the existing message |
| GET | /api/v1/notification-channels/{channel_id}/messages |
Channel message list |
| GET | /api/v1/notifications |
Current user notification list; X-FlowNote-Notification-Cursor server high-water header |
| PATCH | /api/v1/notifications/{message_id}/read |
Mark channel message as read |
| POST | /api/v1/handovers |
Create handover and receipts |
| GET | /api/v1/handovers |
List visible handovers |
| GET | /api/v1/handovers/{handover_id} |
Handover detail |
| PATCH | /api/v1/handovers/{handover_id}/receipts/{receipt_id} |
Update handover receipt status |
| POST | /api/v1/reports/drafts |
Create report draft |
| POST | /api/v1/reports |
Advance report status and optionally generate a document while approving |
| GET | /api/v1/reports |
Report list |
| GET | /api/v1/reports/{report_id} |
Report detail |
| GET | /api/v1/reports/{report_id}/lineage |
Visible current and superseded reports in the same correction family |
| GET | /api/v1/reports/{report_id}/sources |
Frozen report source snapshot after current channel-permission revalidation |
| POST | /api/v1/reports/{report_id}/corrections |
Create an independently reviewed correction draft from the current effective approved report |
| POST | /api/v1/ai-search/candidates/rebuild |
Rebuild traceable AI search evidence candidates |
| GET | /api/v1/ai-search/candidates |
List AI search evidence candidates |
| GET | /api/v1/ai-search/quality |
Candidate counts, exclusion reasons, and FieldComment review readiness |
| POST | /api/v1/ai-search/ground-truth-cases |
Save the first approval and provenance for a scoped regression question; the case remains inactive |
| POST | /api/v1/ai-search/ground-truth-cases/{ground_truth_case_id}/second-approval |
Revalidate the frozen evidence snapshot and activate it with a different second approver |
| GET | /api/v1/ai-search/ground-truth-cases |
List active approved questions for the current scope; includePending=true also returns inactive cases awaiting second approval |
| GET | /api/v1/ai-search/ground-truth-datasets |
List immutable scoped ground-truth dataset versions and coverage |
| POST | /api/v1/ai-search/ground-truth-datasets |
Create a draft dataset version from approved ground-truth cases |
| GET | /api/v1/ai-search/ground-truth-datasets/{dataset_version_id} |
Read a dataset version, its cases, coverage, and approval history |
| PUT | /api/v1/ai-search/ground-truth-datasets/{dataset_version_id}/cases |
Replace the case composition of a draft dataset version |
| POST | /api/v1/ai-search/ground-truth-datasets/{dataset_version_id}/transition |
Submit, review, approve, supersede, or retire a dataset version |
| GET | /api/v1/ai-search/field-readiness/sample-plan |
Read the server-fixed 24-cell sample plan and evaluation evidence |
| POST | /api/v1/ai-search/field-readiness/sample-reviews |
Record a 24-cell independent field-readiness sample review or third-person consensus |
| GET | /api/v1/ai-search/field-readiness/sample-reviews |
List immutable sample reviews and disagreement/consensus status |
| GET | /api/v1/ai-search/readiness |
Read separate FIELD_READINESS and SMOKE_REGRESSION readiness, approval/evaluation state, and sanitized operator actions; only the field track can satisfy provider-start gates |
| POST | /api/v1/ai-search/evaluations |
Persist offline ground-truth evidence, exclusion, and ranking regression results |
| GET | /api/v1/ai-search/evaluations |
List stored evaluation runs with an optional dataset-version filter |
| GET | /api/v1/ai-search/evaluations/{run_id} |
Read a stored evaluation run and optionally compare it with another run |
| POST | /api/v1/ai/queries |
Create an evidence search/summary request through the disabled-by-default safety boundary |
| GET | /api/v1/ai/queries/{query_id} |
Read sanitized AI query status and evidence snapshot |
| GET | /api/v1/ai-operations/approvals |
List scoped external-transfer approvals (system-admin) |
| POST | /api/v1/ai-operations/approvals |
Create a scoped external-transfer approval (system-admin) |
| POST | /api/v1/ai-operations/approvals/{approval_id}/revoke |
Revoke an approval immediately |
| GET | /api/v1/ai-operations/provider-reviews |
List provider due-diligence checklists and four-party start decisions |
| POST | /api/v1/ai-operations/provider-reviews |
Record an immutable provider review version as approved, pending, or rejected |
| GET | /api/v1/ai-operations/prompts |
List immutable prompt versions |
| POST | /api/v1/ai-operations/prompts |
Create an immutable prompt version |
| POST | /api/v1/ai-operations/prompts/{prompt_version_id}/review |
Mark a draft prompt reviewed |
| POST | /api/v1/ai-operations/prompts/{prompt_version_id}/approve |
Approve a reviewed prompt |
| POST | /api/v1/ai-operations/prompts/{prompt_version_id}/activate |
Activate an approved prompt and retire the previous active version for the purpose |
| POST | /api/v1/ai-operations/prompts/{prompt_version_id}/retire |
Retire a prompt version |
| GET | /api/v1/ai-operations/policies |
Read global/site kill switch, limits, retention, and export policy |
| PUT | /api/v1/ai-operations/policies |
Update global/site kill switch, limits, retention, and export policy |
| GET | /api/v1/ai-operations/sensitive-data-policies |
List redacted sensitive-policy versions |
| POST | /api/v1/ai-operations/sensitive-data-policies |
Create an immutable sensitive-policy draft |
| GET | /api/v1/ai-operations/sensitive-data-policies/current |
Read current policy and sanitized runtime block category/owner/next action |
| GET | /api/v1/ai-operations/sensitive-data-policies/{policy_id} |
Read one redacted policy version and its latest state tag |
| POST | /api/v1/ai-operations/sensitive-data-policies/{policy_id}/review |
Record review by a different system administrator |
| POST | /api/v1/ai-operations/sensitive-data-policies/{policy_id}/approve |
Record approval by a third system administrator |
| POST | /api/v1/ai-operations/sensitive-data-policies/{policy_id}/activate |
Activate an approved version when no active version exists |
| POST | /api/v1/ai-operations/sensitive-data-policies/{policy_id}/replace |
Atomically supersede the current active version |
| POST | /api/v1/ai-operations/sensitive-data-policies/{policy_id}/withdraw-approval |
Withdraw approval and block new calls when applicable |
| POST | /api/v1/ai-operations/sensitive-data-policies/{policy_id}/retire |
Retire a policy version and preserve its audit history |
| GET | /api/v1/ai-operations/audit/queries |
Read sanitized query/evidence/citation/call metadata |
| GET | /api/v1/ai-operations/audit/events |
Read AI operational change events |
| GET | /api/v1/ai-operations/audit/export |
Export policy-controlled sanitized query audit CSV |
| POST | /api/v1/ai-operations/retention/run |
Manually redact expired query payloads and delete expired response text |
| GET | /api/v1/ai-operations/retention/audit |
Read retention processing metadata |
| GET | /api/v1/ai-operations/queries/{query_id} |
Read scoped query retention state, state tag, legal-hold history, and linked audits |
| POST | /api/v1/ai-operations/queries/{query_id}/expire |
Immediately expire one query in the configured customer/site scope |
| POST | /api/v1/ai-operations/queries/{query_id}/legal-holds |
Place a reasoned legal/audit preservation hold on a scoped query |
| POST | /api/v1/ai-operations/legal-holds/{hold_id}/release |
Release a preservation hold without deleting its history |
The server uses HMAC-signed Bearer access tokens plus the auth_sessions table. Login creates a session. Refresh rotates the access token ID and refresh token hash. Logout revokes the session.
The pilot server is a single customer/site boundary. Optional X-FlowNote-Customer-Scope and X-FlowNote-Site-Scope headers, plus optional login/refresh body scopes, must match the configured boundary. A mismatch is audited and rejected with 404 SCOPE_NOT_FOUND before resource lookup. Login, refresh, and current-user responses return the effective server scope.
Document write responses carry the server-authoritative aggregate revision. Version registration, status changes, publish, tag replacement, and soft delete compare the caller's base revision and relevant latest/published version before committing. Publish, status, and tag mutations store the normalized intent and first successful response in document_mutation_receipts within the same transaction. Replaying the same mutation key and intent returns that response without another revision or audit event; reusing the key for another intent returns a structured HTTP 409 conflict. WPF reads the document back after a successful response and marks the queue SYNCED only after the authoritative status, published version, tags, and revision agree.
Operation-key mutations for document authority, FieldComment review, report workflow transitions and corrections, and work-sequence changes and candidate deliveries also write sync_mutation_receipts and audit_event_envelopes without replacing their domain receipts or audit rows. Optional X-FlowNote-Run-Id and X-Correlation-Id headers link a verification run; the server creates a correlation ID when it is omitted. GET /api/v1/audit-events is restricted to admin and system-admin, combines common envelopes with legacy activity_history, and marks unavailable legacy fields instead of inferring values.
GET /api/v1/change-history derives a read model from audit_event_envelopes; it does not create a second authority table. Governance roles can filter by time, actor/role, device, target, version/revision, result, risk, run, and correlation ID. Channel-restricted targets are omitted for non-members in both list totals and detail. The first page fixes an event ID snapshot anchor so cursor pagination does not duplicate or omit rows when new audit events arrive.
GET /api/v1/operational-readiness combines that audit anchor with current authority tables without storing another snapshot. Area failures remain isolated as NO_DATA; terminal-session and reconciliation counts are restricted to admin/system-admin. The AI field section accepts only ANONYMOUS_FIELD readiness and never adds synthetic or test regression counts to operational totals.
The first server administrator is created only when FLOWNOTE_INITIAL_ADMIN_PASSWORD is supplied and must change that temporary password before using protected APIs. The short admin / 1234 credential exists only in the isolated test environment and legacy WPF local compatibility data; the server does not seed it in local or production environments.
Server account lifecycle APIs require admin or system-admin. Temporary passwords are request-only sensitive values, force a password change after first login, and are never returned. The python -m app.ops.server_accounts command remains an emergency/server-console path.
GET /api/v1/tags requires any active authenticated account because equipment, line, process, and error tags can expose a site's operating structure. Creating tags requires a document-write role. All document, FieldComment, access log, work sequence, report, and AI search candidate endpoints use the authentication and role policies described in docs/api.md.
Work sequence reads require an authenticated user and writes use the document-write role policy. The server is authoritative for the board aggregate: meaningful item add, reorder, and status mutations conditionally advance board_revision, store exactly one change-history row and one work_sequence_mutation_receipts row in the same transaction, and return WORK_SEQUENCE_STALE_REVISION when another client wins the base revision. Retrying the same intent with the same mutation key returns the stored first response; reusing the key for another intent returns IDEMPOTENCY_KEY_REUSED. No-op reorder or status requests are rejected without consuming a revision.
FieldComment review writes use the server-authoritative review_revision. A caller can send baseReviewRevision and mutationKey; WPF always sends both. One conditional update advances the revision, and the review change plus field_comment_review_mutation_receipts row commit together. Replaying the same key and intent returns the first response snapshot, while stale revisions and key reuse return structured 409 conflicts. Attachment uploads can also bind multipart parentCommentId and fileSha256; parent, request hash, and stored-file hash mismatches are rejected without retaining a new attachment/file row.
When FLOWNOTE_FIELD_COMMENT_INDEPENDENT_REVIEW_REQUIRED=true, a red-signal or conflicting FieldComment cannot move to REVIEWED, SELECTED, EXCLUDED, or ARCHIVED when the decision actor is the same user recorded in analyzed_by.
Report workflow mutations use DRAFT → REVIEWED → APPROVED → ARCHIVED; omitted reportStatus remains backward-compatible as APPROVED, and direct DRAFT → APPROVED remains allowed. Every transition revalidates frozen source eligibility, version/revision/hash and channel permission, conditionally advances report_revision, and commits the report, sources, optional generated document/version, aggregate hashes, and report_mutation_receipts row in one transaction. Sources can only be supplied or replaced while the report is DRAFT or AI_DRAFTED. A document can only be generated while approving and keeps the explicit documentStatus instead of becoming published implicitly. Archiving also archives the linked generated document and its versions while preserving report sources and receipts. Historical report reads preserve the frozen source snapshot while rechecking current channel permission. Invalid transitions, document-generation status mismatches, duplicate generated documents, stale/orphan sources, stale report revision, client/server hash mismatch, and mutation-key reuse return structured conflicts.
An effective approved report can create one correction draft through /api/v1/reports/{report_id}/corrections. The request either copies the complete frozen source snapshot or supplies a complete replacement set, and source or channel-access changes fail without silently dropping evidence. The correction repeats review before approval. Approval atomically makes it the effective family report, projects the previous report as SUPERSEDED, archives the previous generated document, and creates a new IN_REVIEW document that still requires the separate publication workflow.
공개 소스의 기능 탐색은 처음 실행하기의 격리된 loopback API 평가 절차를 사용할 수 있다. 이 결과를 운영 연동 스모크나 고객 현장 승인으로 기록하지 않는다.
프로젝트의 서버 변경 연동 검증은 승인된 개발 PC에서 기존 외부 배포 권한으로 운영 서버에 반영한 뒤 운영 HTTPS health와 스모크로 확인한다. 운영 서버 DB·storage를 개발 PC로 복사하지 않는다. SSH 대상, 개인키, 비밀번호, 토큰과 운영 환경 파일은 저장소에 기록하지 않는다.
Useful settings:
FLOWNOTE_ENVIRONMENTorFLOWNOTE_ENV: defaultlocalFLOWNOTE_API_HOST: default127.0.0.1FLOWNOTE_API_PORT: default5184FLOWNOTE_DATABASE_URL: defaultsqlite:///./data/flownote.sqlite3FLOWNOTE_TEST_DATABASE_URL: defaultsqlite:///./data/flownote.test.sqlite3FLOWNOTE_DATABASE_ECHO: defaultfalseFLOWNOTE_STORAGE_ROOT: default./storageFLOWNOTE_FIELD_COMMENT_ATTACHMENT_MAX_BYTES: default20971520FLOWNOTE_CONTROLLED_COPY_MAX_BYTES: default524288000FLOWNOTE_CONTROLLED_COPY_TICKET_EXPIRES_SECONDS: default60, normalized to5-300FLOWNOTE_ANDROID_VIEW_GRANT_EXPIRES_SECONDS: default60, normalized to5-300FLOWNOTE_ANDROID_VIEW_AUTO_CLOSE_SECONDS: default300FLOWNOTE_ANDROID_VIEW_MAX_BYTES: default52428800(50 MiB)FLOWNOTE_ANDROID_VIEW_MAX_TEXT_BYTES: default5242880(5 MiB)FLOWNOTE_ANDROID_VIEW_MAX_PDF_PAGES: default200FLOWNOTE_SESSION_COOKIE_NAME: defaultflownote_sessionFLOWNOTE_INITIAL_ADMIN_PASSWORD: required only when a fresh server DB creates its firstadmin; leave no value in committed filesFLOWNOTE_ACCESS_TOKEN_SECRET: non-local/testenvironments reject the public placeholder and values shorter than 32 charactersFLOWNOTE_ACCESS_TOKEN_EXPIRES_MINUTES: default480FLOWNOTE_REFRESH_TOKEN_EXPIRES_DAYS: default14FLOWNOTE_CUSTOMER_SCOPE: single-customer server boundary; falls back toFLOWNOTE_AI_CUSTOMER_SCOPEFLOWNOTE_SITE_SCOPE: single-site server boundary; falls back toFLOWNOTE_AI_SITE_SCOPEFLOWNOTE_FIELD_COMMENT_INDEPENDENT_REVIEW_REQUIRED: defaulttrueFLOWNOTE_DOCUMENT_APPROVAL_WORKFLOW_ENFORCED: defaulttrue; requires an approved exact-version request for new publicationFLOWNOTE_DOCUMENT_APPROVAL_REQUESTER_REVIEWER_SEPARATION: default unset; the site must explicitly allow or require separation when requester and reviewer are the same userFLOWNOTE_DOCUMENT_APPROVAL_REQUESTER_PUBLISHER_SEPARATION: default unset; the site must explicitly allow or require separation when requester and publisher are the same userFLOWNOTE_RESTORE_FAULT_CODE: default empty; 복구 장애 실기 전용이며partial_restore,old_database_new_files,missing_file,wrong_server_epoch만 허용FLOWNOTE_RESTORE_BLOCK_REASON: default empty; 복구 장애 차단 사유FLOWNOTE_RESTORE_PILOT_RUN_ID: default empty; 장애 실기 run IDFLOWNOTE_RESTORE_BACKUP_SET_ID: default empty; 복구에 사용한 익명 backup set IDFLOWNOTE_RESTORE_APPROVAL_ID: default empty; 복구 승인 IDFLOWNOTE_RESTORE_RESPONSIBLE_OWNER: default empty; 담당자 역할 IDFLOWNOTE_AI_EXTERNAL_CALL_ENABLED: defaultfalseFLOWNOTE_AI_READINESS_GATE_ENABLED: defaulttrue; 현재 고객·현장·DB scope의 근거/승인 질문/회귀 기준 미달 시 운영 provider 호출 차단FLOWNOTE_AI_PROVIDER: defaultUNCONFIGUREDFLOWNOTE_AI_MODEL: defaultUNCONFIGUREDFLOWNOTE_AI_CUSTOMER_SCOPE: defaultDEFAULTFLOWNOTE_AI_SITE_SCOPE: defaultDEFAULTFLOWNOTE_AI_PROVIDER_EXCERPT_MAX_CHARS: default600, constrained to100-4000FLOWNOTE_AI_PROVIDER_MAX_SOURCES: default12, constrained to1-100FLOWNOTE_AI_PROVIDER_ADAPTER_MODE: defaultDISABLED;FAKE또는 명시적 시험용NETWORK_TEST만 허용FLOWNOTE_AI_FAKE_SCENARIOS: defaultSUCCESS; fake adapter 결정적 시나리오 목록FLOWNOTE_AI_PROVIDER_ENDPOINT:NETWORK_TEST전용 HTTPS JSON endpointFLOWNOTE_AI_NETWORK_TEST_SCOPE_ENABLED: defaultfalse;environment=test와 함께 있어야 네트워크 adapter 생성FLOWNOTE_AI_NETWORK_TIMEOUT_SECONDS: default30, constrained to1-120FLOWNOTE_AI_PROVIDER_MAX_ATTEMPTS: default3, constrained to1-5; timeout, 429, 5xx만 재시도FLOWNOTE_AI_PROVIDER_RESPONSE_MAX_BYTES: default65536, constrained to1024-1048576FLOWNOTE_AI_RETENTION_SCHEDULER_ENABLED: defaulttrue; 서버 lifespan에서 만료 보존 작업을 주기 실행FLOWNOTE_AI_RETENTION_SCHEDULER_INTERVAL_SECONDS: default3600, constrained to60-86400
FLOWNOTE_DATABASE_URL은 FastAPI 서버 전용 DB를 가리켜야 하며 WPF의 FLOWNOTE_LOCAL_DATA_DIR/FLOWNOTE_LOCAL_DATABASE_PATH와 같은 SQLite 파일을 사용하지 않는다. 초기화는 기존 WPF documents/document_versions 열 구성을 감지하면 Base.metadata.create_all() 전에 RuntimeError로 중단해 서버 테이블을 추가하지 않는다.
FLOWNOTE_RESTORE_FAULT_CODE를 설정하면 나머지 복구 식별자 네 개도 모두 있어야 한다. 하나라도 빠지거나 지원하지 않는 장애 코드이면 sync manifest가 503으로 실패한다. 이 값은 별도 PC 복구 실기에서 WPF 차단·재결합 증거를 묶는 표지이며 운영 원본 데이터에 장애를 만드는 기능이 아니다. 승인 뒤에는 서버를 정상 종료하고 FLOWNOTE_RESTORE_* 값을 제거해 다시 시작해야 정상 manifest가 반환된다. 익명 ID와 담당자 역할 ID만 사용하고 고객명, 담당자 실명, 경로와 비밀값은 기록하지 않는다.
cd services\api
.\.venv\Scripts\python.exe -m pytestThe current scripts/verify-preserved-tests.ps1 guards are 212 FastAPI cases, 120 WPF Core cases, and 39 Android unit tests. The repository does not publish prior test databases, logs, uploads, run IDs, or raw results. Run the commands in the testing guide from a clean clone and judge the checked-out commit from that execution. The same guide explains local artifact cleanup and the separate approved-HTTPS smoke procedure.
The system-admin sensitive-data-policy API manages immutable customer/site versions through draft, independently reviewed, independently approved, active, superseded, approval-withdrawn, and retired states. List/detail/audit responses expose only sanitized metadata, content hashes, and item counts; raw terms, customer identifiers, endpoint values, and credentials are not returned. Mutations use stable operation keys, state tags, explicit confirmation values, and read-back. The provider boundary rechecks the active policy snapshot immediately before the call and after the response. The generic network adapter is restricted to explicit test scope and remains disabled by default; provider-specific production activation is not configured. The separate ai_operational_policies API manages kill switches, limits, retention periods, and audit-export permission. Query and retention audit operations are restricted to the configured customer/site scope. The server lifespan runs expired-query retention on the configured interval, while system-admin can run scoped bulk retention, expire one query, or place and release a reasoned legal hold. An active hold blocks all three expiry paths. WPF mutations send a stable operationKey and the latest detail stateTag; duplicate/lost-response retries return the original result, while stale, already-expired, already-released, and concurrent operations return 409. Legal-hold rows and linked audit history are never deleted by release or expiry.
Test SQLite DBs, logs, upload files, and generated samples are Git-ignored. Use python scripts/reset_local_test_data.py from the repository root to preview cleanup and add --apply to reset them.