Files

Contract API

FastAPI service for V2 contract workflows.

Storage

Contract list, detail, workspace tasks and approval timeline data use the SQLAlchemy repository. Local development defaults to SQLite so the V2 main flow can run without extra services:

CONTRACT_API_DATABASE_URL=sqlite+pysqlite:///.runtime/contract-api.sqlite3

Production can switch to PostgreSQL with the same repository:

CONTRACT_API_DATABASE_URL=postgresql+psycopg://contract:contract@localhost:5432/yuqei_contract
CONTRACT_API_DATABASE_AUTO_CREATE=false
CONTRACT_API_SEED_DEMO_DATA=false

Run migrations from this service directory:

cd yuqei-contract-platform/services/contract-api
python -m alembic upgrade head

Local Run

cd yuqei-contract-platform/services/contract-api
python -m uvicorn yuqei_contract_api.main:app --app-dir src --reload --port 8100

Run the contract review worker in another terminal when testing async AI review:

cd yuqei-contract-platform/services/contract-api
$env:PYTHONPATH="src;../../../yuqei-ai-sdk-python/src"
python -m yuqei_contract_api.review_worker

Process one queued review task batch and exit:

python -m yuqei_contract_api.review_worker --run-once --limit 1

The legal-QA browser flow uses POST /api/v1/legal/qa/jobs, polls GET /api/v1/legal/qa/jobs/{job_id}, and exposes explicit retry and human handoff actions. Contract API only applies tenant/user authorization and proxies these operations; the durable model task and provider audit remain owned by AI Platform. The older synchronous legal-QA endpoint remains temporarily available for compatible internal callers.

Run Enterprise Playbook calendar schedules, impact analysis, notifications, secret-grace cleanup, and dead-letter alert evaluation in a separate worker:

cd yuqei-contract-platform/services/contract-api
$env:PYTHONPATH="src;../../../yuqei-ai-sdk-python/src"
python -m yuqei_contract_api.playbook_governance_worker

This worker also leases and runs the P1-07.1 pilot anomaly scanner, reconciles strict reliable-contract-decision evidence, and enqueues work-calendar SLA escalations into the existing notification delivery queue. Run python -m yuqei_contract_api.playbook_governance_worker --run-once after deployment to verify the complete governance cycle.

Google Calendar and Microsoft Graph sources require a provider client ID and secret plus exactly one dedicated OAuth token-encryption secret source. The authorization callback defaults to http://localhost:3000/admin/playbook; use an HTTPS callback outside local development. See .env.example for the exact variables. Refresh tokens and incremental cursors are encrypted at rest, and scheduled sources are claimed by a database lease before synchronization.

DingTalk and WeCom sources use each tenant's internal-app credentials instead of a global OAuth client. Admins enter DingTalk AppKey/AppSecret plus a calendar owner UnionID, or WeCom CorpID/CorpSecret plus cal_id; the secrets and short-lived access tokens use the same dedicated encryption key and are never returned. DingTalk persists the provider syncToken; WeCom performs a complete calendar snapshot and computes the materialized difference locally because the schedule-list API does not expose an equivalent incremental cursor.

Health endpoints:

  • GET /health
  • GET /api/v1/health
  • GET /api/v1/runtime/config-check
  • python -m yuqei_contract_api.review_worker --health

/api/v1/runtime/config-check is the deployment guardrail. It flags unsafe runtime settings such as production SQLite, production auto table creation, enabled demo seed data, invalid AI Platform URL, invalid worker intervals, inconsistent identity delivery mode, missing identity rate-limit secrets, or an empty file storage directory.

Contract review worker production variables:

CONTRACT_API_ENVIRONMENT=production
CONTRACT_API_DATABASE_URL=postgresql+psycopg://...
CONTRACT_API_DATABASE_AUTO_CREATE=false
CONTRACT_API_SEED_DEMO_DATA=false
CONTRACT_API_FILE_STORAGE_DIR=/data/contract-files
CONTRACT_API_AI_PLATFORM_BASE_URL=http://ai-platform-api:8101
CONTRACT_API_AI_PLATFORM_TIMEOUT_SECONDS=60
CONTRACT_API_UVICORN_WORKERS=1
CONTRACT_API_READ_CACHE_TTL_SECONDS=2
CONTRACT_API_REVIEW_WORKER_NAME=contract-review-worker-1
CONTRACT_API_REVIEW_WORKER_POLL_INTERVAL_SECONDS=30
CONTRACT_API_REVIEW_WORKER_BATCH_LIMIT=5
CONTRACT_API_IDENTITY_EMAIL_DELIVERY_MODE=disabled
CONTRACT_API_IDENTITY_SELF_SERVICE_ENABLED=false
CONTRACT_API_IDENTITY_MANUAL_INVITATION_ENABLED=true
CONTRACT_API_IDENTITY_RATE_LIMIT_SECRET=LOAD_A_STABLE_RANDOM_SECRET_OF_AT_LEAST_32_CHARACTERS

CONTRACT_API_AI_PLATFORM_TIMEOUT_SECONDS covers the complete Contract-to-AI request and must exceed AI_PLATFORM_PROVIDER_REQUEST_TIMEOUT_SECONDS by at least five seconds. For example, use 240 when staging a Provider timeout of 180 seconds.

The disabled mode keeps login and administrator-managed one-time invitation links available while public company registration, password reset, and email verification remain off. When enterprise email becomes available, switch to smtp, set manual invitations to false, and configure the SMTP variables from .env.example. The production web proxy must overwrite public X-Real-IP / X-Forwarded-For headers before Contract Web forwards the validated client IP to Contract API for rate limiting.

GET /api/v1/identity/platform-access requires a valid configured proxy key on this endpoint independently of global development mode. It returns only the current identity's platform-access boolean and capability codes; it does not expose the administrator roster.

After migrations, initialize the first production administrator from a protected password file. The command is idempotent and will not replace an existing credential unless --force-rotate is supplied:

python -m yuqei_contract_api.identity_bootstrap `
  --tenant-id default `
  --company-name "平台租户" `
  --email platform-admin@example.com `
  --display-name "平台管理员" `
  --password-file C:\run\secrets\bootstrap-admin-password

After deployment, verify the end-to-end review path from repository root:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File yuqei-infra\scripts\verify-contract-review-worker-flow.ps1 `
  -ContractApiBaseUrl http://localhost:8100 `
  -WorkerExecutionMode docker-compose `
  -RequireConfidence

Use -RequirePrimarySources when the target environment has a populated knowledge base and the review must prove source-backed RAG output.

Reliable decision evidence uses local Ed25519 only for development and isolated UAT. Production must set CONTRACT_API_RELIABLE_EVIDENCE_SIGNING_BACKEND to kms_gateway, mount the gateway service token and CA read-only, and select an immutable asymmetric key version. Keep that signing key separate from the Playbook credential-encryption key. Rotation is performed by registering a new version and submitting a lifecycle change for approval by a different platform administrator. Retirement preserves historical verification, while revocation is irreversible. External audit credentials are issued, rotated, and revoked only after approval by a different platform administrator; complete bearer values are returned once after approval. P1-07.6 uses CONTRACT_API_RELIABLE_EVIDENCE_PROBE_TARGETS_JSON for independent regional KMS gateway probes and CONTRACT_API_RELIABLE_EVIDENCE_ANCHOR_TARGETS_JSON for external immutable checkpoint witnesses. Staging and production fail the runtime configuration gate when either list is empty. Witness credentials and public keys are mounted read-only, and only receipt hashes, witness fingerprints, and external references enter the operations ledger.

Docker Compose Baseline

From repository root:

Copy-Item yuqei-infra\compose\.env.example yuqei-infra\compose\.env
docker compose --env-file yuqei-infra\compose\.env -f yuqei-infra\compose\docker-compose.yml up --build

The compose baseline runs contract-api-migrate before contract-api, and keeps CONTRACT_API_DATABASE_AUTO_CREATE=false inside containers. For production, also set:

CONTRACT_API_ENVIRONMENT=production
CONTRACT_API_SEED_DEMO_DATA=false

After startup:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File yuqei-infra\scripts\verify-v2-runtime.ps1

Test

Run Contract API tests from this service directory. The migration tests resolve alembic.ini and migrations/ relative to the current directory, so running the same command from the repository root is not supported.

Give every full run a new SQLite database and an independent file-storage directory. This prevents a previous run, a local development database, or concurrently running services from changing the result:

cd yuqei-contract-platform/services/contract-api

$testRunId = [guid]::NewGuid().ToString("N")
$testRoot = Join-Path ([System.IO.Path]::GetTempPath()) "yuqei-contract-api-tests-$testRunId"
$testFiles = Join-Path $testRoot "files"
$testDatabase = (Join-Path $testRoot "contract-api.sqlite3").Replace("\", "/")
New-Item -ItemType Directory -Force -Path $testFiles | Out-Null

$env:PYTHONPATH = "src;../../../yuqei-ai-sdk-python/src"
$env:CONTRACT_API_ENVIRONMENT = "test"
$env:CONTRACT_API_DATABASE_URL = "sqlite+pysqlite:///$testDatabase"
$env:CONTRACT_API_DATABASE_AUTO_CREATE = "true"
$env:CONTRACT_API_SEED_DEMO_DATA = "false"
$env:CONTRACT_API_FILE_STORAGE_DIR = $testFiles

python -m pytest -q tests

The PostgreSQL concurrency suite is opt-in. Without CONTRACT_API_POSTGRES_CONCURRENCY_URL it is reported as skipped. Point the variable only at a dedicated non-production PostgreSQL database; the suite creates a random isolated schema, runs migrations inside it, and removes the schema after the test. Supply credentials only through the temporary process environment and never commit them to .env, README examples, logs, or source:

$env:CONTRACT_API_POSTGRES_CONCURRENCY_URL = "postgresql+psycopg://USER:PASSWORD@HOST:5432/TEST_DATABASE" # pragma: allowlist secret
python -m pytest -q tests/test_privileged_identity_postgres_concurrency.py
Remove-Item Env:CONTRACT_API_POSTGRES_CONCURRENCY_URL

Persisted drafting continuation (TP06.24.2)

yuqei-drafting-continuation-worker is a separate polling process, not a thread automatically started inside the API. CONTRACT_API_DRAFTING_WORKER_ENABLED is false by default. After isolated deployment verification, an explicitly enabled worker can reconnect persisted ordinary draft/semantic-review jobs using their original idempotency keys, and continue an opted-in one-generation repair chain. It never adopts a contract or retries a completed, failed, or cancelled model execution. --once explicitly runs one bounded scan even when the daemon switch is off; use it only against an intentionally selected environment.

Candidate leases and reconnect backoff live in the existing workspace JSON; this increment adds no database migration. Use distinct worker names for separate instances. Network reconnects have bounded exponential delays, not a final retry count; failed model executions retain their separate fixed attempt budgets. See the isolated continuation runbook.