Forms Portal — Compliance Controls Mapping¶
Classification: CONFIDENTIAL — Internal Use Only
Document version
v1.0 — 2026-04-18 — derived from forms-backend/compliance/cis-pci-nist-mitre.md at Phase 1 cut.
This document is the authoritative mapping of the Forms Portal (forms.greenpeace.us) implementation against CIS Controls v8, PCI-DSS v4.0, NIST 800-53 Rev 5, and MITRE ATT&CK mitigations. It is reviewed quarterly by the Director of Cyber Security and requires owner sign-off before production cutover (tracked in Cowork Task 6 of the Phase 1 runbook).
The operational/architecture description of the portal lives at Forms Portal — forms.greenpeace.us. This page covers controls and evidence only.
Data classification¶
| Data element | Classification | Handling |
|---|---|---|
| Submission field values (default) | CONFIDENTIAL | AES-256-GCM envelope encryption, per-submission DEK wrapped by KMS |
Searchable field mirrors (searchable: true) |
INTERNAL | Plaintext JSONB column, indexed for admin search |
| Attachments | CONFIDENTIAL | GCS with CMEK, signed URLs, ClamAV scanned, 7-year retention lock |
| Submitter identity (email, username) | INTERNAL | Plaintext columns (operational necessity for audit) |
| Audit log | CONFIDENTIAL | Append-only (REVOKE UPDATE/DELETE), 7-year retention |
| DEK wrapping key | RESTRICTED | Cloud KMS, CMEK, software-protected, automatic 90-day rotation |
Encryption — data in transit¶
| Channel | Protocol | Enforcement |
|---|---|---|
| Browser → Cloud Run | TLS 1.3, HSTS 2yr + preload | Cloud Run managed cert; HSTS header set in app.py |
| Cloud Run → Cloud SQL | TLS 1.3 + mTLS via Cloud SQL Connector | IAM auth; enable_iam_auth=True in db.py |
| Cloud Run → KMS / GCS / Secret Manager | TLS 1.3 (Google private endpoints) | Service account OAuth2 via ADC |
| Cloud Run → HappyFox | HTTPS (TLS 1.2+) | Validated in requests call |
| Cloud Run → VPC (private IP) | TLS via Cloud SQL Connector | vpc-egress=private-ranges-only |
Encryption — data at rest¶
| Asset | Cipher | Key |
|---|---|---|
| Cloud SQL storage | AES-256 (Google-managed layer) + CMEK (customer-managed) | gpus-forms-cmek |
| Cloud SQL automated backups | Same as instance | Inherited |
| Submission field values | AES-256-GCM | Per-submission DEK, wrapped by KMS key gpus-forms-dek-wrapper |
| GCS attachments bucket | AES-256 + CMEK | gpus-forms-cmek |
| GCS backup bucket | AES-256 + CMEK | gpus-forms-cmek |
| Secret Manager | AES-256 (Google-managed) | Managed |
CIS Controls v8¶
| Control | Title | Implementation |
|---|---|---|
| 3.11 | Encrypt Sensitive Data at Rest | CMEK on Cloud SQL + GCS; AES-256-GCM envelope on submission fields |
| 3.12 | Segment Data Processing | Dedicated service account gpus-forms-backend@; private IP; VPC connector |
| 4.4 | Firewall | Cloud SQL private IP only; Cloud Armor WAF at edge; Cloud Run no-allow-unauthenticated |
| 5.1 | Account Management | Okta SSO via OIDC; users table mirrors Okta identity; roles admin/viewer only |
| 6.3 | Multi-factor Authentication | MFA enforced by Okta policy at tenant level |
| 6.8 | Privileged Account Access | Admin role granted in users table; audited via user_granted/user_revoked events |
| 8.2 | Audit Log Collection | Append-only audit_log table; structured JSON to Cloud Logging → CEDAR |
| 8.3 | Log Storage | 7-year retention; Cloud Logging sink to GCS with bucket lock |
| 8.5 | Centralized Log Management | Cloud Logging → CEDAR Elasticsearch (existing pipeline) |
| 8.11 | Audit Log Review | Wazuh rules 100020–100025 on MAPLE; SOC dashboard Tickets tab |
| 10.6 | Vulnerability Scanning | Cloud Build step runs bandit + pip-audit; OAK OpenVAS weekly; Artifact Registry vuln scanning |
| 13.1 | Threat Detection | Wazuh rules trigger SOC auto-ticketing at level ≥ 10 |
| 16.1 | Secure Application Development | Pydantic input validation; parameterized SQL via SQLAlchemy; CSRF tokens; security headers |
PCI-DSS v4.0¶
Forms portal does not process cardholder data. PCI-DSS mapping documented for defense-in-depth alignment only.
| Req | Implementation |
|---|---|
| 1.2.1 | Inbound traffic restricted — Cloud Run auth required, Cloud Armor WAF filters |
| 2.2.1 | Secure configuration — CIS-hardened base image, distroless python, non-root container user |
| 3.5 | Key management — KMS-wrapped DEK; rule 100024 fires on decrypt failure |
| 3.6 | Key rotation — KMS automatic 90-day rotation; re-encrypt job runs on key version change |
| 4.1 | Strong cryptography for transmission — TLS 1.3, HSTS preload |
| 6.5.9 | Protect against CSRF — Flask-WTF CSRF tokens; rule 100022 logs rejects |
| 7.1 | Access to data limited to need — forms_viewer RLS role; admin actions audited |
| 8.3.6 | Password complexity — N/A (Okta SSO, no passwords in forms portal) |
| 10.2.1–10.2.7 | Audit trails — audit_log captures auth, admin, decrypt, export events |
| 10.3 | Audit trail protection — REVOKE UPDATE/DELETE on audit_log; central forwarding to CEDAR |
| 10.7 | Log retention — 7 years |
| 11.3 | Vulnerability scans — OpenVAS weekly (OAK); image scan on every build |
NIST 800-53 Rev 5¶
| Control | Implementation |
|---|---|
| AC-2 | Account Management — Okta + users table sync |
| AC-3 | Access Enforcement — @require_role decorators; Postgres RLS |
| AC-6 | Least Privilege — 2 roles only; service account scoped to Cloud SQL client + KMS encrypter/decrypter + GCS object creator/viewer |
| AU-2 | Event Logging — audit_log table + Cloud Logging |
| AU-6 | Audit Record Review — Wazuh rules + SOC dashboard |
| AU-9 | Protection of Audit Information — append-only, REVOKE UPDATE/DELETE |
| AU-11 | Audit Record Retention — 7 years |
| CM-7 | Least Functionality — minimal container, no shell, distroless-style |
| IA-2 | Identification & Authentication — Okta OIDC, JWT verification |
| IA-5 | Authenticator Management — handled by Okta |
| SC-8 | Transmission Confidentiality — TLS 1.3 everywhere |
| SC-12 | Cryptographic Key Establishment — KMS-managed CMEK + DEK |
| SC-13 | Cryptographic Protection — AES-256-GCM, FIPS-validated via BoringCrypto in GCP |
| SC-28 | Protection of Info at Rest — envelope encryption + CMEK |
| SI-4 | System Monitoring — Prometheus + Wazuh |
| SI-10 | Information Input Validation — pydantic |
MITRE ATT&CK mitigations¶
| Technique | Mitigation |
|---|---|
| T1078 (Valid Accounts) | Okta MFA; role-based access; account lifecycle via Okta lifecycle management |
| T1190 (Exploit Public-Facing Application) | Cloud Armor OWASP rules; pydantic input validation; bandit + pip-audit on build |
| T1213 (Data from Information Repositories) | RLS on submissions; decrypt events audited; bulk export rule 100025 |
| T1537 (Transfer Data to Cloud Account) | Egress restricted to private ranges; signed URLs for attachments; bulk export alerts |
| T1552 (Unsecured Credentials) | All secrets in Secret Manager; no passwords in code or env vars; IAM auth for DB |
| T1562 (Impair Defenses) | Audit log append-only at DB role level; separate forms_readonly role for reports |
Control ownership¶
| Area | Owner | Review cadence |
|---|---|---|
| Cryptographic controls | Director of Cyber Security | Quarterly |
| Access controls (Okta + RLS) | Director of Cyber Security | Quarterly |
| Audit log review | SOC | Weekly (via SOC dashboard) |
| Vulnerability scanning | SOC (OAK) | Weekly |
| Key rotation verification | Director of Cyber Security | Quarterly |
| Retention policy enforcement | Director of Cyber Security | Monthly (purge job audit) |
Sign-off before production¶
- [ ] Director of Cyber Security reviews this document
- [ ] Wazuh rules deployed and verified firing on test events
- [ ] Prometheus alerts routed to correct email/Slack channels
- [ ] OAK OpenVAS target added, baseline scan complete with zero criticals
- [ ] Penetration test scope includes forms portal (update
pentest-schedule.md) - [ ] Disaster recovery test completed (restore from GCS backup, verify decrypt works)
- [ ] IRP (
irp.md) updated with forms-portal-specific playbook entries
Rotation verification log¶
Quarterly execution log for Cowork Task 8 (forms-portal credential rotation check) from forms-backend/RUNBOOK-COWORK.md. Each run records one line per check with status PASS / FLAG / ACTION-NEEDED and any operator notes. This skill never rotates secrets automatically — it verifies state and raises follow-ups.
2026-04-20 — Q2 2026 check (automated run)¶
Executed by: Cowork scheduled task forms-portal-credential-rotation-quarterly (agent, unattended — Rajesh not present for interactive walk-through).
Verification evidence available to the agent was limited to the repo — no gcloud CLI, no GCP Console session, and no HappyFox support channel were reachable from the scheduled-task sandbox. Items that require live console state are therefore logged as ACTION-NEEDED for Rajesh to complete manually and back-fill into this log at the next available window.
| # | Check | Status | Notes |
|---|---|---|---|
| 1 | HappyFox credentials rotation (gpus-forms-happyfox-api-key, gpus-forms-happyfox-auth-code) |
ACTION-NEEDED | Requires an outbound ticket/email to HappyFox support (not executable by agent). If HappyFox confirms rotation, procedure is: add new version to Secret Manager, verify /health + one test submission, disable (not delete) previous version. |
| 2 | Okta client secret rotation policy | PASS (with FLAG for MFA) | config.py references OKTA_CLIENT_ID only (SPA); no OKTA_CLIENT_SECRET env var or secret exists. SPA pattern has no secret to rotate (RUNBOOK-COWORK.md Task 4, Option A confirms reuse of existing "Greenpeace.US" SPA app, client id 0oadhpjktd5UfCMDm0x7). FLAG: MFA enforcement on the Okta sign-on policy needs manual confirmation in Okta Admin each quarter — not verifiable from the repo. |
| 3 | KMS key rotation timestamps (gpus-forms-cmek, gpus-forms-dek-wrapper) |
ACTION-NEEDED | Keys were created with --rotation-period=90d per Step 3 of RUNBOOK-CLAUDE-CODE.md, so automatic rotation is configured. Per-version rotation timestamps (must be within the last 100 days) require GCP Console → Security → KMS → keyring gpus-forms (us-central1) and are not visible to the agent. |
| 4 | Cloud SQL backups (gpus-forms-db: 7 retained, PITR enabled, latest <24h) |
ACTION-NEEDED | Requires GCP Console → Cloud SQL → gpus-forms-db → Backups tab. Not verifiable from the repo. |
Overall result: 1 PASS (with secondary FLAG), 3 ACTION-NEEDED.
Follow-up: A 7-day Cowork follow-up has been scheduled (forms-portal-rotation-followup-2026-q2) to walk Rajesh through items 1, 3, and 4 live and back-fill verified statuses into this log. The MFA-enforcement FLAG on item 2 should be closed out during the same session.
2026-07-20 — Q3 2026 check (automated run)¶
Executed by: Cowork scheduled task forms-portal-credential-rotation-quarterly (agent, unattended — Rajesh not present for the interactive walk-through this check is designed around).
Same evidence boundary as the Q2 run: verification was limited to repo state. No gcloud/gsutil CLI, no authenticated GCP Console session, and no HappyFox support channel were reachable from the scheduled-task sandbox (the sandbox is isolated and carries none of the operator's cloud credentials). Items requiring live console state are therefore logged ACTION-NEEDED for Rajesh to complete manually and back-fill here at the next window. Repo-checkable items were re-verified this quarter rather than carried forward.
| # | Check | Status | Notes |
|---|---|---|---|
| 1 | HappyFox credentials rotation (gpus-forms-happyfox-api-key, gpus-forms-happyfox-auth-code) |
ACTION-NEEDED | Requires an outbound ticket/email to HappyFox support — not an action the unattended agent takes (and the task explicitly forbids automatic rotation). If HappyFox confirms rotation: add a new version to each secret in Secret Manager, verify /health + one test submission, then disable (not delete) the prior version. Caveat re-confirmed this quarter: RUNBOOK-CLAUDE-CODE.md (line 336) records the vendor position as "we reuse current values (vendor won't rotate)" — if that still holds, this check's practical outcome is "vendor rotation not available; compensating controls (Secret Manager access scoped to gpus-forms-backend@, no secret in code/env) remain in force." Rajesh should confirm the current vendor stance and record it. |
| 2 | Okta client secret rotation policy | PASS (with FLAG for MFA) | Re-verified in forms-backend/config.py: only OKTA_CLIENT_ID (0oadhpjktd5UfCMDm0x7, default) and OKTA_DOMAIN/OKTA_ISSUER/OKTA_AUDIENCE are referenced — no OKTA_CLIENT_SECRET env var or Secret Manager entry exists anywhere in the backend. The forms app is a public SPA (RUNBOOK-COWORK.md Task 4, Option A — reuse of the existing "Greenpeace.US" SPA app), so there is no confidential-client secret to rotate. FLAG (unchanged from Q2): MFA enforcement on the Okta sign-on policy must be confirmed manually in Okta Admin each quarter; it is not verifiable from the repo. |
| 3 | KMS key rotation timestamps (gpus-forms-cmek, gpus-forms-dek-wrapper) |
ACTION-NEEDED | Both keys were created with --rotation-period=90d (Step 3, RUNBOOK-CLAUDE-CODE.md), so automatic rotation is configured in code/runbook. Actual per-version rotation timestamps (must be within the last 100 days) are only visible in GCP Console → Security → KMS → keyring gpus-forms (us-central1) and cannot be read by the agent. Confirm the primary version's create time on each key is < 100 days old. |
| 4 | Cloud SQL backups (gpus-forms-db: 7 retained, PITR enabled, latest <24h) |
ACTION-NEEDED | Requires GCP Console → Cloud SQL → gpus-forms-db → Backups tab. Not verifiable from the repo. Confirm: exactly 7 automated backups retained, point-in-time recovery enabled, and the most recent backup completed within the last 24 hours. |
Overall result: 1 PASS (with a secondary MFA FLAG), 3 ACTION-NEEDED. No status regressed versus Q2 2026; the ACTION-NEEDED items are unattended-context limitations, not detected control failures.
Follow-up: A 7-day Cowork follow-up has been scheduled (forms-portal-rotation-followup-2026-q3) to walk Rajesh through items 1, 3, and 4 live and back-fill verified statuses into this log. The MFA-enforcement FLAG on item 2 should be closed out in the same session. Note whether the Q2 follow-up (forms-portal-rotation-followup-2026-q2) was completed — if those items were never back-filled, this is the second quarter running without live console verification and should be prioritized.
Retention audit log¶
Monthly execution log for the "Retention policy enforcement" control (control ownership table above, Director of Cyber Security, monthly cadence). Each entry records the previous calendar month's retention purge-job state with status PASS / FLAG / ACTION-NEEDED / INCIDENT. This skill never deletes data — it verifies the purge job ran, that counts are plausible, that a sampled purged row is actually gone, and that the GCS bucket retention lock is intact.
2026-06-01 — May 2026 audit (automated run)¶
Executed by: Cowork scheduled task forms-portal-purge-job-audit-monthly (agent, unattended — Rajesh not present for interactive walk-through).
Verification evidence available to the agent was limited to the repo. The agent had no gcloud CLI, no GCP Console session, no Cloud SQL psql/IAM-auth session, and no GCS console access from the scheduled-task sandbox. Items that require live cloud state are therefore logged as ACTION-NEEDED for Rajesh to complete manually and back-fill into this log at the next available window. The repo state was checked to confirm the purge-job code path still exists and the schema still defines the relevant fields and audit-action enum — both PASS.
| # | Check | Status | Notes |
|---|---|---|---|
| 1 | Purge job ran in May 2026 | ACTION-NEEDED | Requires Cloud Logging filter resource.type="cloud_run_revision" resource.labels.service_name="gpus-forms-backend" labels.job="retention-purge" with time range 2026-05-01T00:00:00Z..2026-06-01T00:00:00Z. Confirm ≥1 successful run. If zero runs found → escalate as INCIDENT and page on-call. Code path (admin_purge_expired audit action, retention_expires_at < NOW() predicate) is still present in forms-backend/models.py and forms-backend/schema/001_init.sql — PASS at the code-existence layer. |
| 2 | Reported counts plausible (submissions / audit rows / attachments / DEK wrappers) | ACTION-NEEDED | Pull structured log fields submissions_purged, audit_rows_purged, attachments_purged, dek_wrappers_retired from the May run(s). Phase-1 cutover was 2026-04-18, so the 7-year retention window (2555 days, see forms table retention_days default in schema/001_init.sql) cannot yet have elapsed for any production submission — the expected May 2026 count is zero for all four metrics. A non-zero count this month is itself a FLAG and warrants investigation (test/staging data leaked into the prod purge path, or retention_expires_at mis-stamped on a form with retention_days < 44). |
| 3 | Spot check one purged submission | N/A (this month) | Conditional on Check 2 returning a non-zero submission count. With the expected zero-purge result for May 2026, there is no purged submission ID to spot-check. Procedure to retain for future months: pick one purged submission_id from log, verify it is absent from submissions, submission_fields, and gpus-forms-attachments, and verify audit_log entries for that submission (submission_created, any submission_viewed, admin_purge_expired) are still present (audit log retention is independent of submission retention — see schema header comments and AU-11 control mapping). |
| 4 | GCS bucket retention lock on gpus-forms-attachments still enabled and unaltered |
ACTION-NEEDED | Requires GCP Console → Cloud Storage → gpus-forms-attachments → Retention tab. Confirm retention policy is locked (lock icon present, not just configured) and the retention period matches the documented 7-year window. Any alteration → CRITICAL FINDING, page Rajesh immediately per task instructions. |
Overall result: 0 PASS, 3 ACTION-NEEDED, 1 N/A. No INCIDENT or CRITICAL state was reachable from the sandbox — but absence of evidence is not evidence of absence, and items 1 and 4 must be closed out by Rajesh before this month's audit can be marked complete.
Expected outcome reminder: For the first ~7 years post-Phase-1 cutover (2026-04-18 → ~2033-04), monthly purge runs should report zero purged submissions/attachments and zero retired DEK wrappers in steady state. The job must still execute monthly (Check 1) and the GCS retention lock must remain intact (Check 4) — those are the two non-trivial checks during the pre-aging period. The job firing with zero rows touched is the expected PASS shape; a missing run is INCIDENT.
Follow-up: A 7-day Cowork follow-up has been scheduled (forms-portal-purge-audit-followup-2026-05) to walk Rajesh through items 1, 2, and 4 live and back-fill verified statuses into this log.
2026-06-15 — Retention value reconciliation + attachment-bucket cleanup (Gate 5)¶
Performed live (operator-attended) during forms 2.5(c) Gate 5.
- Retention value corrected 2563 → 2555 days. The bucket policy had been set to 2563 days — an error with no defensible derivation (7 years = 2555 days exactly; even counting the 2 leap days in 2026–2033 yields 2557). All other sources (DB
retention_daysdefault, everyforms/*.yaml, this controls doc, the IAR) say 7 years / 2555. The GCS policy was re-set to 2555 days, closing the number mismatch. - Noncurrent-version cleanup. Object versioning was found Enabled, so prior "deletions" had only archived objects to noncurrent versions that the retention policy preserved. Three retained-but-invisible liabilities were removed (verified with
gsutil ls -a, all-versions — not live-only): the credentials-bearing pentest PDF (Exploiting Vulnerable Hosts (4e)…pdf, never actually deleted), an EICAR test-virus file, and a superseded screenshot version. Versioning was set to Suspended to stop new noncurrent versions accruing. - Current policy state: retention set to 2555 days, UNLOCKED. Bucket holds 7 live test artifacts, 0 noncurrent versions.
Check 4 status — UPDATED: moves from ACTION-NEEDED (failing) to "policy correct (2555d), lock scheduled." The retention lock is deliberately deferred, not silently closed. Locking is gated on three conditions, all open:
- (a) Bucket confirmed empty of the remaining 7 test artifacts. (Sequencing note: with 2555 now set, those objects are retention-protected; emptying them requires
retention clear → rm → re-set 2555before the lock.) - (b) Versioning disable-vs-suspend decision + a noncurrent-version-expiration lifecycle rule resolved. Currently Suspended; the lifecycle config has only storage-class transitions, no noncurrent expiry — tracked as a T5/controls item.
- (c) A deliberate lock call by the Director of Cyber Security. The lock is irreversible (cannot be shortened or removed once locked), so it is not taken on autopilot.
Until locked, Check 4's monthly verification asserts: policy present at 2555 days, UNLOCKED, and the three lock-preconditions still tracked. A reduction below 2555 or an unexplained clear is a FLAG.
2026-07-18 — Retention-lock review (Task B.1, automated run)¶
Executed by: Cowork scheduled task forms-portal-attachments-retention-lock-review (agent, unattended — Rajesh not present for the interactive walk-through this review requires). No gcloud/GCS console session was reachable from the sandbox; findings are from repo state plus the 2026-06-15 Gate 5 entry above. Decision: DO NOT LOCK. The lock was not invoked and cannot be from an unattended session. The lock is irreversible, and three of the preconditions below require a human decision.
Gating check (step 1) — NOT cleanly met.
- Phase 2 has cut over — frontend cutover complete 2026-04-27 (
priorities/gpus-it-priorities.mdchange log v1.3); real submission persistence began 2026-05-08 (Phase 2.5(b), was "theater" before that). - The 90-day production-operation bar is not met under the strict reading: 82 days since the 2026-04-27 frontend cutover, 71 days since real persistence (2026-05-08). Only the due-date driver — 90 days after the 2026-04-18 unlock decision — has elapsed (91 days). Flagged as a discrepancy between the due-date driver and the step-1 "≥90 days in production" gate; resolves in favour of hold given irreversibility.
Lock preconditions (from 2026-06-15 Gate 5) — still open. No evidence any of the three has closed since 2026-06-15: (a) bucket still not confirmed empty of the 7 live test artifacts — locking now would make test data (previously incl. an EICAR file and a credentials-bearing pentest PDF) immutable for 7 years; (b) versioning disable-vs-suspend + noncurrent-expiry lifecycle rule unresolved; (c) deliberate lock call by the Director of Cyber Security not yet made.
Category retention review (step 2). All 28 active forms/*.yaml declare retention_days: 2555 (7 years) uniformly. Categories present: hr, finance, supporter-care, it, facilities, other (the Data Team forms — data-analysis-request, data-request-form, database-* — sit under other). Assessment of whether an immutable 7-year floor fits each — all items below need Rajesh's confirmation, none is a confirmed exception yet:
- Human Resources — 7 years is a reasonable floor; some records (pension/benefits, employment history) may warrant longer. A floor does not force deletion at 7 years, so "keep longer" is not a conflict. Likely OK.
- Finance — 7 years aligns with IRS/tax record retention. Likely correct.
- Supporter Care (
frontline-form-request,refund-processing-form) — primary concern. An immutable 7-year floor forbids early deletion, which conflicts with data-minimization and right-to-erasure obligations (CCPA / state privacy laws / GDPR for any EU supporters) for donor PII. Refund/financial records may need 7 years, but non-financial supporter PII may need to be deletable on request. Needs a decision before an irreversible floor is applied. - Data Team /
otheroperational tickets (IT, facilities, data requests) — a 7-year immutable floor likely over-retains short-lived operational attachments, enlarging breach-exposure surface. Data-minimization concern, not a legal conflict.
Recommendation. Do not lock until: (1) the three Gate-5 preconditions close (bucket emptied of test artifacts, versioning/lifecycle resolved, deliberate lock call); (2) the 90-day production-operation bar is met (~2026-07-26 by frontend cutover, ~2026-08-06 by real persistence); and (3) Rajesh confirms Supporter Care / operational-ticket retention — if either needs sub-7-year deletion, the single-bucket immutable-lock model is the wrong shape and the choice is split-buckets-per-category vs. application-level lifecycle within one bucket (the per-form retention_days metadata already supports the latter). If confirmed to lock after all preconditions clear, the exact interactive command is gsutil retention lock gs://gpus-forms-attachments — irreversible; run only with explicit understanding that no object can be deleted before 7 years, even by an owner.
Check 4 status — unchanged: policy present at 2555 days, UNLOCKED, three preconditions still tracked (plus the new Supporter Care erasure-rights question). This review scheduled a 60-day follow-up.
Forms Portal Compliance Controls · v1.0 · 2026-04-18 · GPUS-IT · Classification: CONFIDENTIAL — Internal Use Only