Privatelinks GraphQL#2944
Draft
jshearer wants to merge 6 commits into
Draft
Conversation
…te/` and `ops/tasks/private/` prefixes The generic invite-link APIs (`createInviteLink`, `deleteInviteLink`, `inviteLinks`) should not let users manage or discover delegation under the platform-owned `ops/dp/private/<tenant>/` and `ops/tasks/private/<tenant>/` prefixes. Those grants are derived from the customer catalog prefix at data-plane provisioning time, so direct user-driven invite links there would bypass that ownership relationship. * createInviteLink and deleteInviteLink reject those prefixes before authorization, so even an explicit admin grant on an internal prefix cannot be used to mint or revoke a delegation link there. * inviteLinks filters those prefixes out of the listing query as defense-in-depth against directly-inserted rows or unexpected admin grants. * `ensure_private_data_plane_grants()` is unchanged; its sub-prefix `read` grants are a separate RLS workaround.
…oller The GraphQL API needs typed visibility into the same `PrivateLink` shape the data-plane controller (DPC) reads from the `private_links json[]` column. Define the types in `models` so both crates share a single source of truth, and re-export from `data-plane-controller::shared::stack` so existing DPC callers keep compiling unchanged. * Serde shape is preserved byte-for-byte: untagged enum, declaration order AWS/Azure/GCP, Azure `dns_name`/`resource_type` stay as `String` with `skip_serializing_if = "String::is_empty"`, GCP `all_ports` default/skip behavior unchanged. * Output-side async-graphql derives are added under the existing `async-graphql` feature: `SimpleObject` on each provider struct with explicit GraphQL names, and `Union` on `PrivateLink`. The mutation input type is intentionally left to the GraphQL layer (Phase 4) so the union member names and the one-of field names can be set independently.
…isioning-endpoint fields The `dataPlanes` query now exposes the configured private link config typed against the shared `models::PrivateLink` union, plus the three provisioning-result endpoint columns (`awsLinkEndpoints`, `azureLinkEndpoints`, `gcpPscEndpoints`) as opaque JSON arrays. Raw `private_links` rows are fetched once per page and parsed lazily so a malformed historical row produces a descriptive field error naming the data plane and link index, rather than breaking the whole query selection. * fetch_data_plane_details extended to SELECT the four new columns; the three endpoint columns are nullable `json[]` and map NULL to an empty Vec. * private_links.sql fixture adds a private data plane with one entry of each variant plus an AWS provisioning result, and the `aliceCo/` → `ops/dp/private/aliceCo/` role grant so authorization picks the row up.
… mutation Adds a single mutation that replaces the entire `private_links` column for a private data plane. The provided list is the new full state; the data-plane controller converges to it on its next poll. Authorization is the interim shape that mirrors the existing data-plane deployment model: `read` on the private data-plane name is sufficient. This will be replaced with `manage_dataplane` once the orthogonal capability model lands. * `OneofObject` + `InputObject` derives added to `models::PrivateLink` and its provider structs, so the mutation accepts `Vec<models::PrivateLink>` directly with no input-side type duplication or conversion shim. Output and input GraphQL types are generated from the same Rust source. * Name parsing rejects public data planes and anything that doesn't strictly match `ops/dp/private/<tenant>/<provider>-<region>-c<n>`, before authorization or any DB write. * Per-provider validation: AWS `service_name` matches `com.amazonaws.vpce.<region>.vpce-svc-*` with matching region; GCP `service_attachment` matches `projects/*/regions/*/serviceAttachments/*` with matching region; Azure requires `service_name` and `location`; required arrays must be non-empty. * Returns the post-write `DataPlane` (re-fetched via the same path as the `dataPlanes` query) so callers see the bumped `updated_at` and canonical parsed `privateLinks`.
These fields are semantically optional in the est-dry-dock Pulumi contract. Previously both `models::PrivateLink` and the generated GraphQL schema represented them as required `String` with the empty string as the "absent" sentinel, producing a `String!` GraphQL contract that required clients to know about the empty-string convention.
Change the model to `Option<String>` with a serde adapter that maps incoming missing fields and incoming empty strings to `None`, and serializes both `None` and `Some("")` to a missing field. The wire format is byte-for-byte unchanged: historical rows with either representation round-trip identically. The Pulumi consumer (est-dry-dock) already receives "field absent" via `skip_serializing_if`; its Pydantic model defaults the field back to `""` independently and checks via `!= ""` / truthy, so no est-dry-dock change is required.
The GraphQL surface now exposes `dnsName: String` and `resourceType: String` (nullable) on both `AzurePrivateLink` and `AzurePrivateLinkInput`.
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.
WIP