Add in-app account deletion (#319)
## Summary - Add self-service deletion for the authenticated customer or subuser identity only. - Preserve shared customer grants, reset keys, bookings, order bookings, vehicles, invoices, and legally required history. - Require password/TOTP or a fresh deletion-specific, five-minute, single-use WebAuthn assertion. - Reject support impersonation and expired legacy plain-session tokens. - Use durable database throttling, transactional request processing, a durable outbox, and terminal `manual_review` state. - Keep API and worker default-off behind separate `account_deletion.api_enabled` and `account_deletion.worker_enabled` module-config flags. ## Safe rollout 1. Keep both flags disabled. 2. Run `php scripts/account-deletion-schema.php check`. 3. If needed, run `php scripts/account-deletion-schema.php apply --yes`, then rerun `check` until `ready:true`. 4. Deploy the frontend companion PR while the API remains disabled. 5. Enable `api_enabled` for a controlled canary; verify password and passwordless request flows plus immediate authentication revocation. 6. Inspect queued request/outbox state, then enable `worker_enabled`. 7. Verify anonymization, preserved tenant/history data, outbox delivery, retries, and manual-review behavior before broad rollout. ## Verification - Account deletion unit tests: 2 passed, 43 assertions. - PHP lint, both OpenAPI YAML parses, runtime-DDL scan, destructive-scope scan, and `git diff --check` passed. - Full API/unit/integration evidence is required from exact-head CI; local Docker is unavailable and shared-vendor tests were explicitly discarded. ## Security notes - Schema mutation is CLI-only; web and cron paths perform read-only readiness checks. - Runtime behavior fails closed when schema/config/throttle/delivery prerequisites are unavailable.
This commit is contained in:
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
fwrite(STDERR, "This command is CLI-only.\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
const WD = __DIR__ . '/../services/nginx/app';
|
||||
require_once WD . '/vendor/autoload.php';
|
||||
require_once WD . '/config.php';
|
||||
require_once WD . '/classes/db.php';
|
||||
require_once WD . '/classes/account_deletion_schema_bootstrap.php';
|
||||
|
||||
$response = null;
|
||||
$db = new \classes\db($CONFIG_DB);
|
||||
$db->connect();
|
||||
$command = $argv[1] ?? 'check';
|
||||
|
||||
if ($command === 'apply') {
|
||||
if (($argv[2] ?? '') !== '--yes') {
|
||||
fwrite(STDERR, "Refusing schema mutation without: apply --yes\n");
|
||||
exit(2);
|
||||
}
|
||||
\classes\account_deletion_schema_bootstrap::apply();
|
||||
}
|
||||
|
||||
if (!in_array($command, ['check', 'apply'], true)) {
|
||||
fwrite(STDERR, "Usage: scripts/account-deletion-schema.php check|apply --yes\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
$status = \classes\account_deletion_schema_bootstrap::check();
|
||||
fwrite(STDOUT, json_encode($status, JSON_UNESCAPED_SLASHES) . PHP_EOL);
|
||||
exit($status['ready'] ? 0 : 1);
|
||||
Reference in New Issue
Block a user