Skip to content

feat: PostgREST image registry and schema preflight (PLAT-499, PLAT-500)#300

Open
moizpgedge wants to merge 3 commits intomainfrom
feat/PLAT-499/PLAT-500/PostgREST-prerequisites/image-wiring
Open

feat: PostgREST image registry and schema preflight (PLAT-499, PLAT-500)#300
moizpgedge wants to merge 3 commits intomainfrom
feat/PLAT-499/PLAT-500/PostgREST-prerequisites/image-wiring

Conversation

@moizpgedge
Copy link
Contributor

@moizpgedge moizpgedge commented Mar 17, 2026

Register PostgREST container images and add schema/role preflight validation

Pins PostgREST to 14.5 from the pgEdge registry (ghcr.io/pgedge/postgrest:14.5). The bare ref lets serviceImageTag prepend the configured ImageRepositoryHost, consistent with how MCP images are registered.

Add schema/role preflight validation before provisioning PostgREST. Before the plan step, the workflow connects to the primary Postgres instance and verifies that all configured schemas and the anonymous role exist. Missing objects produce a clear error, e.g.:

schema "api" does not exist in database "storefront";
create it before deploying PostgREST

PLAT-499, PLAT-500

Summary

Registers the PostgREST service image (ghcr.io/pgedge/postgrest:14.5) and adds a preflight check that validates required schemas and the anonymous role exist in Postgres before PostgREST provisioning begins. Also extends the service version pattern to accept two-part versions (e.g., 14.5) in both the Goa design and server-side validation.

All PostgREST config fields are optional with sensible defaults — db_schemas defaults to "public" and db_anon_role defaults to "pgedge_application_read_only". A minimal PostgREST deployment requires only "config": {}.
Optional:-

  "config": {
          "db_schemas": "api",
          "db_anon_role": "web_anon"
        }

Changes

  • Register postgrest service image pinned to 14.5 via ghcr.io/pgedge/postgrest.
  • Extend serviceVersionPattern and semverPattern to accept two-part versions (\d+.\d+) in addition to three-part semver and latest.
  • Add ValidatePostgRESTPrereqs activity: connects to the primary instance (with Patroni-based primary discovery and reachable-instance fallback) and checks all configured schemas and the anonymous role exist.
  • Run preflight in UpdateDatabase workflow before the plan step; invalid config fails fast with a clear error.
  • All PostgREST config fields are optional: db_schemas → "public", db_anon_role → "pgedge_application_read_only", db_pool → 10, max_rows → 1000.

Testing

go test ./server/internal/orchestrator/swarm/... -v
go test ./server/internal/api/apiv1/... -v
go test ./server/internal/workflows/...

Checklist

  • Tests added or updated (unit and/or e2e, as needed)
  • Documentation updated (if needed)
  • Issue is linked (branch name or URL in PR description)
  • Changelog entry added for user-facing behavior changes
  • Breaking changes (if any) are clearly called out in the PR description

Notes for Reviewers

Preflight connects read-only; falls back to the first reachable instance if primary lookup via Patroni fails (stale data edge case)
"config": {} is valid and sufficient for a standard PostgREST deployment against the public schema

Register PostgREST container images:
- `latest` → `docker.io/postgrest/postgrest:latest`
- `v14.5` → `docker.io/postgrest/postgrest:v14.5`

The `docker.io/` prefix ensures `serviceImageTag` treats the ref as
fully-qualified and does not prepend the configured
`ImageRepositoryHost`.

Add schema/role preflight validation before provisioning PostgREST.
Before the plan step, the workflow connects to the primary Postgres
instance and verifies that all configured schemas and the anonymous
role exist. Missing objects produce a clear error, e.g.:

  schema "api" does not exist in database "storefront";
  create it before deploying PostgREST

PLAT-499, PLAT-500
@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4cbc2319-5d81-4baa-9bdd-46a288b01193

📥 Commits

Reviewing files that changed from the base of the PR and between e80ba4c and 99689f0.

📒 Files selected for processing (8)
  • server/internal/orchestrator/swarm/postgrest_config.go
  • server/internal/orchestrator/swarm/postgrest_config_resource.go
  • server/internal/orchestrator/swarm/postgrest_config_test.go
  • server/internal/orchestrator/swarm/resources.go
  • server/internal/orchestrator/swarm/service_spec.go
  • server/internal/orchestrator/swarm/service_spec_test.go
  • server/internal/orchestrator/swarm/service_user_role.go
  • server/internal/orchestrator/swarm/service_user_role_test.go

📝 Walkthrough

Walkthrough

Adds PostgREST support across the stack: new image version 14.5 and tests; generates and persists postgrest.conf via a new Swarm resource; builds PostgREST container specs and env; adds user-role behavior for PostgREST; implements prereq validation activities and invokes them before provisioning; extends version validation to allow two-part versions like 14.5.

Changes

Cohort / File(s) Summary
Service Image Registry & Tests
server/internal/orchestrator/swarm/service_images.go, server/internal/orchestrator/swarm/service_images_test.go
Adds postgrest:14.5 image entry (tag resolved via repository host) and extends tests to cover GetServiceImage, supported-version expectations, and constraint checks for PostgREST.
Preflight Validation Activities & Workflow Integration
server/internal/workflows/activities/activities.go, server/internal/workflows/activities/validate_postgrest_prereqs.go, server/internal/workflows/update_database.go
Registers and implements ValidatePostgRESTPrereqs activity (TLS read-only connection to primary, verify schemas and optional anon role, aggregate errors) and invokes it in the database update workflow to abort provisioning on failure.
PostgREST Config Resource & Generation + Tests
server/internal/orchestrator/swarm/postgrest_config.go, server/internal/orchestrator/swarm/postgrest_config_resource.go, server/internal/orchestrator/swarm/postgrest_config_test.go, server/internal/orchestrator/swarm/resources.go
Adds config generator GeneratePostgRESTConfig, a new PostgRESTConfigResource to write postgrest.conf into the service data dir, registers the resource type, and adds tests validating emitted config keys and absence of credentials.
Service Container Spec & Tests
server/internal/orchestrator/swarm/service_spec.go, server/internal/orchestrator/swarm/service_spec_test.go
Refactors container spec to support per-service types; adds buildPostgRESTEnvVars, configures command/args/env/healthcheck/mounts for PostgREST, and adds unit tests for command, healthcheck, env vars, mounts, and user handling.
Service User Role Logic & Tests
server/internal/orchestrator/swarm/service_user_role.go, server/internal/orchestrator/swarm/service_user_role_test.go
Adds ServiceType and DBAnonRole to ServiceUserRole, bumps resource version, introduces roleAttributesAndGrants() to compute role attributes and SQL grants per service type (PostgREST vs MCP), and adds tests covering attribute/grant variants and edge cases.
API Validation and Docs
api/apiv1/design/database.go, server/internal/api/apiv1/validate.go, server/internal/api/apiv1/validate_test.go
Broadens service version regex to accept two-part versions (e.g., 14.5) in addition to three-part SemVer and latest; updates docs/examples and adds a test case validating postgrest with version 14.5.

Poem

🐇 I nibble tags and find a shiny 14.5,
craft a config, tuck secrets out of sight.
I TLS-hop to primary, count each schema's gate,
listen for anon role—no missing trait.
Preflight done, I thump once—ready to take flight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.04% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: PostgREST image registry and schema preflight (PLAT-499, PLAT-500)' clearly summarizes the main changes: PostgREST image registration, schema preflight validation, and references the related issues.
Description check ✅ Passed The description is comprehensive and follows the template structure with Summary, Changes, Testing, and Checklist sections. It clearly explains the implementation, includes actionable examples, and links to related issues.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/PLAT-499/PLAT-500/PostgREST-prerequisites/image-wiring
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/internal/orchestrator/swarm/service_images_test.go`:
- Around line 109-114: The test case named "postgrest service has versions"
currently only checks the length; change it to assert the actual returned
versions from SupportedServiceVersions("postgrest") rather than just count:
collect the map keys returned by SupportedServiceVersions, sort them (or compare
as an unordered set) and assert they equal the expected set {"latest","v14.5"}
so the test fails if any other two-element combination is returned; update the
assertion in the test function in service_images_test.go accordingly (use the
test helper or testify/reflect-based equality as appropriate).

In `@server/internal/workflows/activities/validate_postgrest_prereqs.go`:
- Around line 134-150: The code currently falls back to db.Instances[0] when
Patroni discovery fails; instead, iterate db.Instances and pick the first
instance whose connection info successfully resolves via
a.DatabaseService.GetInstanceConnectionInfo (and optionally verify
reachability), then assign its InstanceID to primaryInstanceID. Update the
fallback block so that if primaryInstanceID == "" you loop through db.Instances,
call a.DatabaseService.GetInstanceConnectionInfo(ctx, databaseID,
inst.InstanceID), use the first call that returns no error (and/or a lightweight
reachability check) to set primaryInstanceID, rather than unconditionally using
db.Instances[0]; keep references to patroni.NewClient and
database.GetPrimaryInstanceID unchanged.

In `@server/internal/workflows/update_database.go`:
- Around line 106-117: The code currently ignores parseErrs from
ParsePostgRESTServiceConfig and only runs preflight when parseErrs is empty;
change this to fail fast when parseErrs is non-empty: if
ParsePostgRESTServiceConfig returns any parseErrs, return an error (wrap via
handleError) describing the invalid PostgREST config and include parseErrs
details so the workflow stops before planning; keep the existing preflight call
(ExecuteValidatePostgRESTPrereqs with ValidatePostgRESTPrereqsInput using
cfg.DBSchemas and cfg.DBAnonRole) for the valid-path case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fc966f26-8fa1-4b2b-acdb-4b3e618ba438

📥 Commits

Reviewing files that changed from the base of the PR and between e35708d and b8b714d.

📒 Files selected for processing (5)
  • server/internal/orchestrator/swarm/service_images.go
  • server/internal/orchestrator/swarm/service_images_test.go
  • server/internal/workflows/activities/activities.go
  • server/internal/workflows/activities/validate_postgrest_prereqs.go
  • server/internal/workflows/update_database.go

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Registers PostgREST service images in the Swarm service image registry and adds a preflight workflow activity that validates required Postgres schemas and the configured anonymous role exist before provisioning PostgREST.

Changes:

  • Add ValidatePostgRESTPrereqs workflow activity to connect to the database and verify configured schemas + anon role exist.
  • Run the PostgREST preflight checks in UpdateDatabase before planning/provisioning.
  • Register PostgREST service image versions and extend Swarm service image tests accordingly.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
server/internal/workflows/update_database.go Runs PostgREST prerequisite validation before the plan/apply phases.
server/internal/workflows/activities/validate_postgrest_prereqs.go New activity that connects to a DB instance and checks schemas + anon role existence.
server/internal/workflows/activities/activities.go Registers the new ValidatePostgRESTPrereqs activity with the worker.
server/internal/orchestrator/swarm/service_images.go Adds PostgREST image entries (latest, v14.5) to the service image registry.
server/internal/orchestrator/swarm/service_images_test.go Adds/updates tests to cover PostgREST image resolution and version listing expectations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/internal/workflows/activities/validate_postgrest_prereqs.go`:
- Around line 160-163: The current call to
DatabaseService.GetInstanceConnectionInfo(databaseID, primaryInstanceID) returns
an error and bails out immediately; instead, when that call fails, fall back to
the previously-captured reachable connection info (e.g., reachableConnInfo /
reachableInstanceID) for the read-only checks: attempt to assign connInfo =
reachableConnInfo and proceed (optionally log or warn that primary lookup failed
and reachable instance is being used); only return the wrapped error if no
reachableConnInfo is available. Update the logic around connInfo,
primaryInstanceID, and reachableConnInfo in the ValidatePostgrestPrereqs flow to
prefer the primary result but accept the reachable fallback on error.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b76c1ad0-1ff4-4562-aa87-401f010c42b8

📥 Commits

Reviewing files that changed from the base of the PR and between b8b714d and 389adf9.

📒 Files selected for processing (4)
  • server/internal/orchestrator/swarm/service_images.go
  • server/internal/orchestrator/swarm/service_images_test.go
  • server/internal/workflows/activities/validate_postgrest_prereqs.go
  • server/internal/workflows/update_database.go

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

- Pin postgrest image to ghcr.io/pgedge/postgrest:14.5
- Extend version pattern to accept two-part versions (e.g. 14.5)
- Add ValidatePostgRESTPrereqs activity with Patroni primary
  discovery and reachable-instance fallback
- Fail fast on invalid PostgREST config before plan step
- All config fields optional: db_schemas defaults to "public",
  db_anon_role to "pgedge_application_read_only"

PLAT-499, PLAT-500
@moizpgedge moizpgedge requested a review from rshoemaker March 17, 2026 15:20
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
server/internal/api/apiv1/validate.go (1)

260-264: Consider updating the error message to reflect two-part version support.

The error message references "semver format (e.g., '1.0.0')" but the validation now also accepts two-part versions like "14.5". Consider updating the message to be more accurate:

-		err := errors.New("version must be in semver format (e.g., '1.0.0') or 'latest'")
+		err := errors.New("version must be in format 'X.Y' or 'X.Y.Z' (e.g., '14.5', '1.0.0') or 'latest'")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/internal/api/apiv1/validate.go` around lines 260 - 264, The validation
error message for svc.Version is out of date: update the string created where
svc.Version is checked (the block using semverPattern, newValidationError,
appendPath, and errs) to accurately state that versions may be semver (e.g.,
"1.0.0"), two-part versions (e.g., "14.5"), or "latest" so the message matches
the accepted formats.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@server/internal/api/apiv1/validate.go`:
- Around line 260-264: The validation error message for svc.Version is out of
date: update the string created where svc.Version is checked (the block using
semverPattern, newValidationError, appendPath, and errs) to accurately state
that versions may be semver (e.g., "1.0.0"), two-part versions (e.g., "14.5"),
or "latest" so the message matches the accepted formats.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 90ed306b-89ae-47e2-b987-2070738d8d56

📥 Commits

Reviewing files that changed from the base of the PR and between 389adf9 and e80ba4c.

⛔ Files ignored due to path filters (7)
  • api/apiv1/gen/control_plane/service.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/client/types.go is excluded by !**/gen/**
  • api/apiv1/gen/http/control_plane/server/types.go is excluded by !**/gen/**
  • api/apiv1/gen/http/openapi.json is excluded by !**/gen/**
  • api/apiv1/gen/http/openapi.yaml is excluded by !**/gen/**
  • api/apiv1/gen/http/openapi3.json is excluded by !**/gen/**
  • api/apiv1/gen/http/openapi3.yaml is excluded by !**/gen/**
📒 Files selected for processing (6)
  • api/apiv1/design/database.go
  • server/internal/api/apiv1/validate.go
  • server/internal/api/apiv1/validate_test.go
  • server/internal/orchestrator/swarm/service_images.go
  • server/internal/orchestrator/swarm/service_images_test.go
  • server/internal/workflows/activities/validate_postgrest_prereqs.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • server/internal/orchestrator/swarm/service_images_test.go
  • server/internal/workflows/activities/validate_postgrest_prereqs.go

@moizpgedge moizpgedge force-pushed the feat/PLAT-499/PLAT-500/PostgREST-prerequisites/image-wiring branch from 99689f0 to e80ba4c Compare March 18, 2026 14:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants