feat(contrail): wire contrail-community in-process + gate via CI#585
Merged
Conversation
PR #582 appended `FROM release AS ingest` at the end of the Dockerfile. deploy-to-dev.yml's `docker build` runs without `--target`, so Docker defaults to the LAST stage in the Dockerfile — silently flipped the API image to the ingest variant (CMD `npm run contrail:ingest`). New API pods on b518567 crashloop because no HTTP server binds to port 3000 and the readiness probe gets connection refused. The `ingest` target was never load-bearing: the Phase E Deployment manifest overrides `command: ["npm", "run", "contrail:ingest"]` on the single-replica ingest pod, so the same `release` image works for both roles. Dropping the extra target restores `release` as the default and unblocks the dev rollout.
Rebuild the contrail tarballs from the fork's feat/pr30-pr31-integration branch and add @atmo-dev/contrail-community as a sixth vendored package. prepare-contrail-deps.sh now builds and packs contrail-community alongside the other five; package.json pins it as a file: dependency. Verified at runtime against both sqlite (in-memory) and postgres: contrail + community schemas apply and createApp wires the spaces/community routes.
Add CredentialKeyMaterial, AuthorityConfig, SpacesConfig, and CommunityIntegration types to the @atmo-dev/contrail ambient module. Extend ContrailConfig with spaces? and community?, ContrailOptions with communityIntegration?, and add generateAuthoritySigningKey() function declaration. Add new @atmo-dev/contrail-community module declaration with createCommunityIntegration().
Adds two opt-in sections to buildContrailConfig(): spaces.authority (enabled by CONTRAIL_AUTHORITY_SIGNING_KEY) and community (enabled by CONTRAIL_COMMUNITY_MASTER_KEY), both absent by default so existing ingest-only deployments are unaffected.
…ion key Keep the vendor 'masterKey' config property (contrail-community API); feed it from CONTRAIL_COMMUNITY_ENCRYPTION_KEY. Avoids 'master' terminology in our env vars, locals, and docs.
Append a Contrail block to env-example-relational covering CONTRAIL_DATABASE_URL, CONTRAIL_COMMUNITY_ENCRYPTION_KEY, CONTRAIL_AUTHORITY_SIGNING_KEY and the optional network vars, noting that community XRPC routes mount only when both the community block and spaces.authority are configured. Wire the same CONTRAIL_* vars into the api service in docker-compose-dev.yml: CONTRAIL_DATABASE_URL reuses the local Postgres (schema-isolated), the two keys interpolate from the shell at `up` time so no key material lands in git. SERVICE_DID is intentionally omitted — contrail.config defaults it and it is a shared var read elsewhere.
Assert GET /xrpc/net.openmeet.community.getHealth returns 401 (auth-gated, mounted) and explicitly not 404 (unmounted) or 503 (provider down). Gated on the community env vars since the routes only register when both community and spaces.authority are configured.
- Add CONTRAIL_* (DB URL on the CI Postgres, schema-isolated, plus two throwaway CI test keys) to env-example-relational-ci so the contrail-xrpc e2e suite runs in CI instead of skipping. Verified end to end in the layered CI stack: 5/5 pass, including community.getHealth. - Delete contrail-community-loader.spec.ts: it only asserted an export is a function (covered by the wiring spec + e2e + runtime) and triggered a jest vm-modules teardown race when sharing a worker with sibling contrail specs (om-mcv0) — a real risk to the maxWorkers=2 unit job.
Address PR #585 review feedback: - buildContrailConfig now assembles the community block only when BOTH CONTRAIL_COMMUNITY_ENCRYPTION_KEY and CONTRAIL_AUTHORITY_SIGNING_KEY are set. Community routes are service-auth gated against credentials the authority signs/verifies, so an encryption key alone is a half-configured mount the vendor integration can't serve. Previously the partial-config path (encryption key, no authority) reached createCommunityIntegration at startup untested; now it is dropped with a warning. This matches the documented "both keys" behavior in env-example-relational. - Remove unused ContrailProvider.isCommunityReady() (no callers; the /xrpc middleware forwards through handle() unconditionally). communityEnabled is retained for the init log line. - Mark the committed CI test keys as DO-NOT-REUSE / inert outside CI. - Add trailing newline to env-example-relational. Tests: src/contrail config suite 4/4 (adds a partial-config drop+warn case); wiring/idempotency unchanged.
Contributor
Author
|
Addressed review feedback in
Still open (not code): the three rebuilt vendor tarballs ( |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Wires contrail-community (the PR #30 + PR #31 integration, vendored from our fork) into openmeet-api in-process — the same pattern as contrail-ingest, no new service and no
main.tschange. The existingContrailProvideris extended so that when both community secrets are configured, thecommunity.*/space.*XRPC routes mount alongside the existingnet.openmeet.*read routes.This is Track D Phase 1, Step 2 (in-process wiring). Step 1 (vendoring
@atmo-dev/contrail-community) landed earlier on this branch.Changes
@atmo-dev/contrail-communitytarball as a 6thfile:dep;prepare-contrail-deps.shbuilds/packs all 6 packages.contrail.config.ts): env-gatedcommunityblock (CONTRAIL_COMMUNITY_ENCRYPTION_KEY, AES-GCM envelope key) andspaces.authorityblock (CONTRAIL_AUTHORITY_SIGNING_KEY, ES256 P-256 JWK). Community routes mount only when both are present — otherwise the provider behaves exactly as before.contrail-loader.ts): import the 3 contrail ESM subpaths sequentially rather than viaPromise.all. Under jest--experimental-vm-modulesthe concurrent cold link of the shared contrail-base/appview subgraph races and throws "module is not linked"; sequential import fixes it (and also fixed the pre-existing brokencontrail-init-idempotency.spec.ts).communityIntegrationinto theContrailinstance when configured;init()applies the spaces+community schema next to the ingest schema.env-example-relationaland wiredCONTRAIL_*into the api service indocker-compose-dev.yml(DB URL reuses local Postgres, schema-isolated; the keys interpolate from the shell atuptime — no key material in git).CONTRAIL_*(DB URL + throwaway test keys) toenv-example-relational-ciso the contrail e2e actually runs in CI instead of skipping silently. Deleted a standalone loader spec that only asserted "an export is a function" and reproduced the jest vm-modules teardown race under--maxWorkers=2.Test plan (e2e, not checkboxes)
test/contrail/contrail-xrpc.e2e-spec.ts— existing 4 read-route cases plus a new community-mount probe:GET /xrpc/net.openmeet.community.getHealth→ 401 (mounted + service-auth gated), asserted explicitly not 404 (unmounted) or 503 (provider down). Gated on the 3 community env vars.docker-compose.relational.ci.yaml+atproto-devnet+docker-compose-ci-devnet.yml, api built fromrelational.e2e.Dockerfile):Tests: 5 passed, 5 total,EXIT_CODE=0. This PR makes GitHub Actions run that same harness.src/contrailjest suite (config 3/3, wiring 2/2, idempotency 2/2) green under--maxWorkers=2(CI's worker model).Notes for reviewers
5e7622b) makes the same Dockerfile removal that already landed in main via fix(docker): drop ingest target so release stays default build stage #583's squash — so the Dockerfile diff shows in the file view but is a no-op against main (both sides made the identical removal; merges with no net change). The real payload is the 12contrailcommits on top.om-uwis+om-k55c, deferred post-release.