Skip to content

Policy lifecycle

Every policy carries a status. The status tells you whether the policy is still being written, currently active, or retired, and it controls whether the extension enforces it. This page walks through every status, how policies move between them, and which transitions are actually wired up versus still on the roadmap.

Status Short description Enforced by extension?
Suggestion AI-extracted from an uploaded document, pasted text, or URL — not yet human-reviewed. Lives in the Policy Inbox. No
Draft Human-authored, or an accepted Suggestion that’s now being edited. No
Submitted Submitted for a publisher’s review (Phase 4 — see below). No
Published Live. Violation detection runs against this policy. Yes
Blocked Administratively blocked from enforcement. Still visible in the library, no longer checked. No
Deprecated Retired. Kept for audit history. No
Dismissed A Suggestion explicitly dismissed from the Inbox without being accepted. Kept on the row (rather than deleted) so a re-scan of the same source doesn’t resurface it. No

These are the values of the PolicyStatus enum in the backend schema. Suggestion/Draft/Submitted/Published/Blocked/Deprecated surface as status pills in the policies list, detail view, and revision history; Dismissed only ever appears in the Inbox’s collapsed Dismissed section (see The Policy Inbox) — it never reaches the main policies list.

The two independent flags: status and isActive

Section titled “The two independent flags: status and isActive”

Every policy also has an isActive boolean, worth knowing about separately from status:

  • isActive = true only when status is PUBLISHED. Setting a policy to PUBLISHED sets isActive: true; every other status sets it false.
  • isActive does not account for the effective/expiry window, but detection does. isActive is set purely from status (it stays true on a PUBLISHED policy whose expiry date has passed, and Analytics’ “Active policies” count still reads it that way). The detection path, however, evaluates the validity window on every check: a policy is retrieved and enforced only while it is in force — its effectiveDate (if set) has arrived and its expiryDate (if set) has not passed. The window is judged against the time of the check, in UTC; an expiry date counts through the whole of that calendar day (a policy “expiring 2026-09-29” is enforced until 2026-09-30 00:00 UTC), and an effective date starts at 00:00 UTC of that day.

The extension’s detection path filters { isActive: true, deletedAt: null } and the validity window — it does not filter on status directly (redundant today, since PUBLISHED is the only status that sets isActive: true). The same window check runs on every retrieval route: the in-memory path for small tenants, the database search functions that serve larger tenants, and the reference-fact path.

This is the real transition map in the current release — nothing here requires roadmap features.

  1. Create from scratch → status is DRAFT, isActive: false.
  2. Save changes repeatedly → stays DRAFT; each save writes a DRAFT_SAVE revision.
  3. Publish (requires APPROVE_POLICIES, i.e. Policy Lead or Admin) → status becomes PUBLISHED, isActive: true. A PUBLISHED revision is recorded. Embedding regeneration runs async (~30 seconds) — after which the extension starts flagging matches.

AI-assisted: Inbox → Suggestion → Draft → Published

Section titled “AI-assisted: Inbox → Suggestion → Draft → Published”
  1. Import a document, URL, or pasted text in the Policy Inbox — PolicyBot creates one or more SUGGESTION rows.
  2. Accept as draft from the Inbox → status stays SUGGESTION until edited. Specifically, the current implementation allows publishing SUGGESTION directly without first converting to DRAFT.
  3. Edit → any manual edit on a Suggestion writes it back as DRAFT on next save. (Author attribution POLICYBOT is preserved on the original INITIAL revision; subsequent human edits are tagged HUMAN.)
  4. Publish → same as above. Publishers can publish DRAFT or SUGGESTION policies directly.
  5. Dismiss from Inbox → the suggestion’s status becomes DISMISSED. It’s a real PolicyStatus value (not a separate flag), which is why it doesn’t resurface on re-scans of the same source — it’s not given a DEPRECATED status.

Published policies can be edited in place. A save:

  • Creates a new revision (DRAFT_SAVE if save-as-draft, PUBLISHED if save-and-publish).
  • Does not drop the policy back to DRAFT — it stays PUBLISHED throughout.
  • Triggers a new embedding job (again async ~30 seconds).

This is deliberate. The published-vs-draft distinction isn’t “is this version public,” it’s “are we ready to enforce any version.” Once a policy is published, it stays public; the revision history carries the narrative of what changed.

From the History tab on a policy, Restore takes any prior revision and writes it as a new RESTORED revision on top of the current state. The status doesn’t change — restoring on a published policy keeps it published; restoring on a draft keeps it a draft.

These two statuses exist in the schema but no UI transition currently ships. They’re there because the backend tracks them, but there’s no “Block” or “Deprecate” button on a policy detail view right now. If you find a policy in BLOCKED or DEPRECATED status, it was set that way via a direct database or admin-API operation — not a user action.

The practical implication: to stop a published policy from being enforced you can either delete it or set an expiry date — once that day has passed the policy is no longer retrieved for detection, even though it remains PUBLISHED and isActive: true in the record (see The two independent flags above). Setting a future effective date likewise holds a published policy back until that day. A proper “unpublish” or “deprecate” user action is planned but not shipped.

The policy versioning roadmap describes four phases. Phases 1–3 are in. Phase 4’s review workflow is the one most relevant to this page.

Phase 4: submit / approve / request-changes / withdraw (not yet shipped)

Section titled “Phase 4: submit / approve / request-changes / withdraw (not yet shipped)”

The enum SUBMITTED is in the schema, but the UI and endpoints that move policies into and out of it are planned, not live. When shipped:

Transition Who triggers Result
Submit for review Any editor of a DRAFT or SUGGESTION Status → SUBMITTED, reviewer assigned. Policy becomes read-only until the reviewer acts.
Approve Assigned reviewer (with APPROVE_POLICIES) Calls publish — status → PUBLISHED.
Request changes Assigned reviewer (with APPROVE_POLICIES) Status → DRAFT. A required comment explains what to fix.
Withdraw Original author Status → DRAFT. Used if the author realizes the submission was premature.

Self-approval will be blocked (the reviewer cannot equal the submitter). Reviewer suggestions pre-fill the policy area’s point-of-contact when available.

Until Phase 4 ships, the effective workflow is:

  • Contributors write drafts; a Lead or Admin publishes when ready. Coordination happens in comments on the policy or outside InPolicy.
  • Policy Leads can also publish their own drafts without ceremony.

Shipped in its own branch and partially merged. Threaded comments with optional text-anchor, resolve/reopen, and @mentions. See Comments & collaboration for what’s currently available.

Not yet in the schema. When it ships, acknowledgements will live on a separate surface from the policy lifecycle. Users will acknowledge specific versions of published policies, and re-acknowledgement will be triggered by certain kinds of edits.

The UI displays status with color-coded pills (exact tokens are in the policy-repository redesign):

  • Suggestion — purple/lavender
  • Draft — warm yellow
  • Submitted — blue (visible in lists even though the workflow isn’t shipped — if a policy somehow ends up in this state, you’ll see the pill)
  • Published — green
  • Blocked — red
  • Deprecated — gray

Severity is a separate dimension from status. A 5/5 severity policy that’s still a Draft does nothing — severity only matters once the policy is Published and isActive.

Promotion and demotion — a practical summary

Section titled “Promotion and demotion — a practical summary”
  • Promotion path today: DRAFT (or SUGGESTION accepted from the Inbox) → PUBLISHED. One click by someone with APPROVE_POLICIES.
  • Demotion path today: none via UI beyond the validity window. Policies are edited in place or deleted; setting an expiry date stops enforcement after that day without changing the record’s status (see above). Block/Deprecate are plumbed in the data model but not user-accessible.
  • Promotion path after Phase 4: DRAFT → SUBMITTED → PUBLISHED (via Approve) or back to DRAFT (via Request changes / Withdraw).

If you need to move a policy through a stage that isn’t user-accessible yet — e.g. formally deprecating a legacy policy without deleting the audit trail — contact support; it’s an admin-API operation.