Restore API startup by isolating Bird activation (#334)
Keep Bird activation outside the PHP-FPM/nginx startup path so Bird configuration failures cannot make the core API unavailable. Retain guarded explicit activation and regression coverage.
This commit is contained in:
@@ -2,8 +2,5 @@
|
||||
set -e
|
||||
|
||||
mkdir -p /run/nginx
|
||||
if [ "${CONFIG_DB_TARGET:-live}" = "live" ]; then
|
||||
php /var/www/html/scripts/bird-control-plane-auto-activate.php
|
||||
fi
|
||||
php-fpm -D
|
||||
exec nginx -g "daemon off;"
|
||||
|
||||
@@ -44,15 +44,14 @@ deletion, physical gate actions, arbitrary recipients, attachments, or a
|
||||
generic proxy. Outbound references are durably reserved before a provider
|
||||
request; an ambiguous outcome must be inspected through
|
||||
`/bird/control-plane/v1/messages/by-reference` and is never blindly retried.
|
||||
Credentials and write switches can only be changed by the guarded CLI startup
|
||||
path or its explicit break-glass command, never by a web request.
|
||||
Credentials and write switches can only be changed by the guarded CLI
|
||||
activation command, never by a web request.
|
||||
|
||||
### Schema deployment and preflight
|
||||
|
||||
The durable webhook and outbound-action ledgers use checked-in schema version
|
||||
`1`. Schema changes are never run from a web request or worker. Production
|
||||
startup applies and verifies the schema automatically; these commands remain
|
||||
available for manual preflight and break-glass recovery:
|
||||
`1`. Schema changes are never run from a web request, worker, or core API
|
||||
startup. Use these commands for deployment preflight and recovery:
|
||||
|
||||
```bash
|
||||
php scripts/bird-control-plane-schema.php check
|
||||
@@ -64,15 +63,21 @@ php scripts/bird-control-plane-schema.php check
|
||||
publishes read-only `schema: {ready, version, expectedVersion, missing}` state.
|
||||
Ledger-dependent reads, webhook ingestion, messages, and operational actions
|
||||
fail closed with HTTP `503` and code `bird_schema_not_ready` until the preflight
|
||||
is ready. Production auto-activation applies and verifies the schema before
|
||||
enabling any Bird write switch; the manual command remains a diagnostic and
|
||||
break-glass path.
|
||||
is ready. Explicit activation applies and verifies the schema before enabling
|
||||
any Bird write switch.
|
||||
|
||||
### Fail-closed production auto-activation
|
||||
### Fail-closed production activation
|
||||
|
||||
The Coolify production container runs activation before PHP-FPM or nginx. It
|
||||
first transactionally disables bootstrap readiness and all three write
|
||||
switches. It then canonicalizes the existing legacy workspace/channel
|
||||
Bird activation is deliberately separate from PHP-FPM and nginx startup, so a
|
||||
Bird provider or configuration failure cannot make the core API unavailable.
|
||||
Run the guarded activation explicitly in the deployed API container:
|
||||
|
||||
```bash
|
||||
php /var/www/html/scripts/bird-control-plane-auto-activate.php
|
||||
```
|
||||
|
||||
The command first transactionally disables bootstrap readiness and all three
|
||||
write switches. It then canonicalizes the existing legacy workspace/channel
|
||||
configuration, applies and checks schema version `1`, validates configured
|
||||
channels and conversations, resolves the access-key participant, pins the
|
||||
public webhook URL to
|
||||
@@ -80,6 +85,8 @@ public webhook URL to
|
||||
verifies webhooks while writes remain dark. Only then does one transaction
|
||||
enable bootstrap readiness, the Control Plane, outbound messaging, and
|
||||
operational-action switches, followed by final readiness checks.
|
||||
Any failure returns a non-zero exit code and re-disables the Bird capabilities
|
||||
without stopping or restarting the core API.
|
||||
It preserves existing valid credentials; otherwise it generates distinct
|
||||
48-byte random Control Plane and webhook secrets inside the container. The
|
||||
webhook key remains backend-only.
|
||||
|
||||
@@ -398,16 +398,16 @@ it('accepts staged activation only while every write capability remains disabled
|
||||
expect(bird_control_plane_auto_activation::stagedActivationReady($status))->toBeFalse();
|
||||
});
|
||||
|
||||
it('wires fail-closed startup and a pinned local bootstrap without plaintext exposure', function (): void {
|
||||
it('keeps Bird activation outside core API startup and pins local bootstrap without plaintext exposure', function (): void {
|
||||
$repoRoot = getenv('PLENO_REPO_ROOT_FOR_TESTS');
|
||||
expect($repoRoot)->toBeString()->not->toBe('');
|
||||
$start = file_get_contents($repoRoot . '/services/coolify/api/start.sh');
|
||||
$local = file_get_contents($repoRoot . '/scripts/bird-control-plane-bootstrap-local.sh');
|
||||
$route = file_get_contents(app_path('routes/birdControlPlaneRoute.php'));
|
||||
|
||||
expect($start)->toContain('bird-control-plane-auto-activate.php')
|
||||
->and(strpos($start, 'bird-control-plane-auto-activate.php'))
|
||||
->toBeLessThan(strpos($start, 'php-fpm -D'))
|
||||
expect($start)->not->toContain('bird-control-plane-auto-activate.php')
|
||||
->and($start)->toContain('php-fpm -D')
|
||||
->and($start)->toContain('exec nginx')
|
||||
->and($local)->toContain(
|
||||
"bootstrap_url='https://api.truckwash.io:4433/bird/control-plane/v1/bootstrap'"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user