Card docs/backlog/11-approval-flows.md · Milestone M3 · Blocked-by: M1 (PR #1)
Scope
src/flows/employer-verification.flow.ts, job-publish-review.flow.ts, offer-approval.flow.ts, barrel, wire flows; add 'automation' to requires: in objectstack.config.ts.
This card is the one that expands that capability — AGENTS.md keeps capability expansion tight, so no other dependency, plugin or requires: entry comes with it. Load objectstack-automation (approvals, approval-as-flow-node) and study examples/app-showcase/src/automation/flows/ in the objectstack repo.
- F1
employer_verification — entry when ats_employer.verification_status becomes pending; step 1 approver = position platform_ops, step 2 = platform_admin; approve → verified + notify the employer owner (inbox); reject → rejected, copy the reviewer's comment to verification_note. That note is platform-internal and FLS-masked from employer roles, so the rejection reason the employer sees must not be sourced from it.
- F2
job_publish_review — entry on ats_job.status → pending_review; single approver position platform_ops; approve → published + published_at = now; reject → rejected + rejection_reason from the reviewer comment; notify the job's employer members with access_level == 'admin'.
- F3
offer_approval — entry on ats_offer.status → pending_approval; approver = the employer_admin members of the offer's employer; approve → approved; reject → draft; notify the submitter. This one is the employer's own internal approval — it demonstrates that approval chains are not only a platform-operator device.
Every transition must be legal under the state machines in §02. Do not widen a state machine to make a flow fit — if a flow needs a transition that does not exist, that is a needs_decision.
Also in scope
Org provisioning on approval: when F1 approves an employer, its platform organization and the owner's membership must exist, or every subsequent row-level policy for that employer resolves to zero rows (DESIGN.md §03, "遗留的运维前提"). Seeds cover this for the demo data; F1 covers it for real onboarding.
Acceptance
pnpm validate && pnpm lint && pnpm typecheck green; pnpm validate reports 3 flows.
- In
pnpm dev the three approvals appear in the approver's queue; a rejected job carries rejection_reason.
Out of scope
Email channel configuration; F4–F6 (#7).
Card
docs/backlog/11-approval-flows.md· Milestone M3 · Blocked-by: M1 (PR #1)Scope
src/flows/employer-verification.flow.ts,job-publish-review.flow.ts,offer-approval.flow.ts, barrel, wireflows; add'automation'torequires:inobjectstack.config.ts.This card is the one that expands that capability —
AGENTS.mdkeeps capability expansion tight, so no other dependency, plugin orrequires:entry comes with it. Loadobjectstack-automation(approvals, approval-as-flow-node) and studyexamples/app-showcase/src/automation/flows/in the objectstack repo.Spec —
DESIGN.md§05employer_verification— entry whenats_employer.verification_statusbecomespending; step 1 approver = positionplatform_ops, step 2 =platform_admin; approve →verified+ notify the employer owner (inbox); reject →rejected, copy the reviewer's comment toverification_note. That note is platform-internal and FLS-masked from employer roles, so the rejection reason the employer sees must not be sourced from it.job_publish_review— entry onats_job.status→pending_review; single approver positionplatform_ops; approve →published+published_at = now; reject →rejected+rejection_reasonfrom the reviewer comment; notify the job's employer members withaccess_level == 'admin'.offer_approval— entry onats_offer.status→pending_approval; approver = theemployer_adminmembers of the offer's employer; approve →approved; reject →draft; notify the submitter. This one is the employer's own internal approval — it demonstrates that approval chains are not only a platform-operator device.Every transition must be legal under the state machines in §02. Do not widen a state machine to make a flow fit — if a flow needs a transition that does not exist, that is a
needs_decision.Also in scope
Org provisioning on approval: when F1 approves an employer, its platform organization and the owner's membership must exist, or every subsequent row-level policy for that employer resolves to zero rows (
DESIGN.md§03, "遗留的运维前提"). Seeds cover this for the demo data; F1 covers it for real onboarding.Acceptance
pnpm validate && pnpm lint && pnpm typecheckgreen;pnpm validatereports 3 flows.pnpm devthe three approvals appear in the approver's queue; a rejected job carriesrejection_reason.Out of scope
Email channel configuration; F4–F6 (#7).