Skip to content

feat(gcp): add Cloud SQL and GKE adapters - #155

Merged
hectorvent merged 3 commits into
floci-io:mainfrom
TheSaifZaman:feat/service-coverage
Jul 29, 2026
Merged

feat(gcp): add Cloud SQL and GKE adapters#155
hectorvent merged 3 commits into
floci-io:mainfrom
TheSaifZaman:feat/service-coverage

Conversation

@TheSaifZaman

@TheSaifZaman TheSaifZaman commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Narrowed: messaging moved to #157 and secrets to #156, so this is now just the two GCP services that share the operation-envelope handling. Independent of both — off main.

Service Was Now
GCP Cloud SQL coming_soon list, create, inspect, delete
GCP GKE coming_soon list, create, inspect, delete

Both were coming_soon because the frontend said so — the runtime has been serving them all along. With availability now registry-derived (#153), each is a catalog row plus an adapter and no frontend change.

The thing most worth reviewing

/v1/projects/{p}/locations/{l}/clusters on floci-gcp is not GKE. It is Managed Service for Apache Kafka. It answers 200, returns objects called clusters, and creating one succeeds — so a "GKE adapter" bound there would have looked entirely healthy while listing Redpanda brokers as Kubernetes clusters.

The payload and the container gave it away:

$ curl -s .../v1/projects/floci-local/locations/us-central1/clusters/probe | jq
{ "bootstrapAddress": "172.20.0.5:9092", "vcpuCount": 3, "memoryBytes": 3221225472 }
$ docker ps
floci-kafka-probe   redpandadata/redpanda:latest

GKE lives at /container/v1/... and behaves like Kubernetes:

$ curl -s .../container/v1/projects/floci-local/locations/us-central1/clusters | jq '.clusters[0]'
{ "name": "probe-k8s", "status": "RUNNING", "endpoint": "localhost:6550",
  "currentMasterVersion": "1.30.5-gke.1014001",
  "nodePools": [{"name": "default-pool", "status": "RUNNING"}], "masterAuth": {...} }
$ docker ps
floci-gke-probe-k8s   rancher/k3s:latest

Worth flagging because the capability guard from #153 could not have caught it — the schema and the adapter would have agreed with each other perfectly. There is now a test asserting the adapter calls /container/v1/, with the reason in a comment.

Three operation envelopes

Google's mutations return a receipt, and the shape differs per service. All three are present on this runtime:

Service Shape Embeds the resource?
Cloud Functions / Run {done, response} yes
Cloud SQL sql#operation + targetId no
GKE {status, operationType, targetLink} no

The first cut of Cloud SQL echoed the receipt and surfaced the operation UUID as the resource name. adapter-gcp/operations.ts keeps that discrimination in one place; the two that only name the resource are read back.

Cloud SQL is also PostgreSQL-only on this runtime — it rejects every other engine — so the schema offers Postgres versions rather than the full GCP list.

Verification

pnpm lint, type-check, test, build pass. Against the live stack, both round-trip create → list → inspect → delete with no container left behind:

Cloud SQL: create → postgres:15.18-alpine container, RUNNABLE, ip 172.20.0.5, connectionName floci-local:us-central1:...
GKE:       create → rancher/k3s container, RUNNING, endpoint localhost:6550, default-pool

create spawns real containers, so exercising it locally needs #154 (Docker socket). List, inspect and delete work without it, and nothing here depends on that PR to compile or test.

README service matrix regenerated.

Type of change

  • Bug fix (fix:)
  • New feature / service UI (feat:)
  • Breaking change (feat!: or fix!:)
  • Docs / chore

Area

  • Frontend (packages/frontend)
  • API / Cloud Proxy (packages/api)
  • Cloud Explorer adapter / schema
  • Build / CI / Docker

Checklist

  • pnpm lint, pnpm type-check, pnpm test, and pnpm build pass locally
  • New or updated tests added where it makes sense (bun test in packages/api)
  • No fake/mock data added
  • Commit messages / PR title follow Conventional Commits

The GCP database cell was empty even though the runtime serves sqladmin — its
`coming_soon` was a frontend assumption, not a runtime fact. With availability
now derived from the registry, registering this adapter is all it takes.

Mirrors the public sqladmin v1beta4 contract. Two behaviours are specific to the
local runtime and worth naming:

- Create answers with a `sql#operation` receipt that names the instance but does
  not embed it, so the adapter reads the instance back rather than echoing the
  receipt — otherwise the operation UUID surfaces as the resource name.
- The runtime backs each instance with a real Postgres container and rejects
  every other engine, so the schema offers PostgreSQL versions only rather than
  the full GCP list.

adapter-gcp/operations.ts keeps the envelope discrimination in one place, since
GKE and Cloud Run return the `{done, response}` shape instead and will need the
same handling.

Verified end to end against floci-gcp 0.5.0: create starts a
postgres:15.18-alpine container and reports the instance RUNNABLE with its IP
and connection name; list, inspect and delete round-trip and leave no container
behind.
The GCP k8s cell was empty while the runtime served GKE the whole time. Backed
by a real k3s container, so clusters report a live API endpoint, master version
and node pools.

Worth recording why the path is `/container/v1/...` rather than the `/v1/...`
the other GCP services use. The runtime serves both, and
`/v1/projects/{p}/locations/{l}/clusters` — the same path shape GKE uses on
container.googleapis.com — is Managed Service for Apache Kafka here. It answers
200, returns something called a cluster, and creating one starts a Redpanda
broker. An adapter bound there would have listed Kafka brokers as Kubernetes
clusters: the exact class of dishonesty the capability guard exists to catch,
except the guard cannot see it because the schema and the adapter would agree
with each other. The distinguishing evidence was the payload (`bootstrapAddress`
on :9092, `vcpuCount`) and the container image the runtime started.

GKE brings a third operation-envelope shape — `{status, operationType,
targetLink}`, naming the cluster by path with no embedded resource — so
operations.ts now resolves a targetLink as well as a targetId.

Verified against floci-gcp 0.5.0: create starts a rancher/k3s container and the
cluster reports RUNNING with its endpoint and default-pool; list, inspect and
delete round-trip and leave no container behind.
@TheSaifZaman
TheSaifZaman requested a review from hectorvent as a code owner July 28, 2026 04:22
@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Registers live GCP Cloud SQL and GKE adapters in the Cloud Explorer registry and expands their schemas for list/create/inspect/delete.

  • Adds GcpCloudSqlAdapter against sqladmin v1beta4 with operation-receipt re-read and Postgres-only create fields.
  • Adds GcpGkeAdapter on /container/v1/.../clusters (not the Kafka clusters path) with operation targetLink resolution.
  • Centralizes GCP operation envelope handling in adapter-gcp/operations.ts and wires both adapters in cloudProxy.ts; regenerates the README service matrix.

Confidence Score: 5/5

This PR appears safe to merge; the prior FIFO create issue is no longer present on the reviewed HEAD, and no remaining blocking failures were identified.

No blocking failure remains. The earlier SQS FifoQueue create gap is addressed by commit cfaf653 (sets Attributes.FifoQueue for .fifo names), and that adapter path is not part of the current HEAD tree under review.

Important Files Changed

Filename Overview
packages/api/src/adapter-gcp/GcpCloudSqlAdapter.ts Cloud SQL adapter lists/creates/gets/deletes instances and re-reads after sql#operation receipts.
packages/api/src/adapter-gcp/GcpGkeAdapter.ts GKE adapter uses /container/v1 paths and resolves create via targetLink re-read.
packages/api/src/adapter-gcp/operations.ts Shared helpers distinguish embedded resources from SQL/GKE operation receipts.
packages/api/src/cloudProxy.ts Registers GcpCloudSqlAdapter and GcpGkeAdapter in the cloud adapter registry.
packages/api/src/cloud-spi/databaseSchema.ts Cloud SQL schema gains create fields, actions, columns, and capability rows.
packages/api/src/cloud-spi/eksSchema.ts GKE schema gains create fields, actions, columns, and capability rows.

Sequence Diagram

sequenceDiagram
  participant UI as Cloud Explorer UI
  participant API as CloudProxy / registry
  participant SQL as GcpCloudSqlAdapter
  participant GKE as GcpGkeAdapter
  participant GCP as floci-gcp :4588
  UI->>API: "create/list/get/delete database|k8s"
  API->>SQL: database ops
  SQL->>GCP: /sql/v1beta4/.../instances
  GCP-->>SQL: "sql#operation or instance"
  SQL->>GCP: GET instance (when receipt only)
  API->>GKE: k8s ops
  GKE->>GCP: /container/v1/.../clusters
  GCP-->>GKE: Operation targetLink or cluster
  GKE->>GCP: GET cluster (when receipt only)
Loading

Reviews (4): Last reviewed commit: "docs: regenerate the service matrix" | Re-trigger Greptile

Comment thread packages/api/src/adapter-aws/AwsSqsAdapter.ts Outdated
@TheSaifZaman
TheSaifZaman force-pushed the feat/service-coverage branch from f08aa4f to 975abf0 Compare July 28, 2026 04:28
@TheSaifZaman

Copy link
Copy Markdown
Contributor Author

Good catch on the FIFO create — that was a real bug and it's fixed.

The adapter accepted a .fifo name and reported the resulting queue as fifo-queue, but never sent Attributes.FifoQueue=true, which real SQS requires.

Worth noting why it survived both layers of verification, since it's a trap for the other service PRs too:

  • The unit test used a stub that accepts any input, so create({queueName: 'orders.fifo'}) resolved happily.
  • Floci core infers FIFO from the .fifo suffix, so creating one against the live runtime also succeeded — it even came back typed fifo-queue, which is what made it look verified end to end.

So both the mock and the emulator were more forgiving than AWS, and the gap would only have shown up against the real service. Fixed by sending the attribute, with tests asserting it is set for a .fifo name and omitted otherwise:

$ curl -s -X POST .../aws/services/messaging/resources -d '{"queueName":"floci-fifo-check.fifo"}'
  create: 201
  type: fifo-queue | arn: arn:aws:sqs:us-east-1:000000000000:floci-fifo-check.fifo

CI is green.

@TheSaifZaman
TheSaifZaman force-pushed the feat/service-coverage branch from cfaf653 to 3f927a5 Compare July 28, 2026 04:50
@TheSaifZaman TheSaifZaman changed the title feat(api): expose Cloud SQL, GKE and messaging through the Cloud Explorer feat(gcp): add Cloud SQL and GKE adapters Jul 28, 2026

@hectorvent hectorvent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for this one, and especially for catching that /v1/projects/{p}/locations/{l}/clusters on the runtime is Managed Kafka, not GKE. That is exactly the kind of trap that would have shipped looking healthy, and pinning the /container/v1/ prefix with a test plus a comment explaining why is the right way to keep it caught. operations.ts centralizing the three operation-envelope shapes is also a nice touch that the other GCP adapters can now lean on.

The split from the original bundle (messaging to #157, secrets to #156) reads well, and keeping Cloud SQL and GKE together here makes sense given they share the envelope handling.

One small behavioral question, not a blocker:

  • In GcpGkeAdapter.create, Number(input.values.initialNodeCount ?? 1) maps an empty string to 0, which passes the Number.isFinite check, so a blank text field could send initialNodeCount: 0 instead of the documented default of 1. Could you treat blank (and non-positive) input as the default? Something like parsing via stringValue first, or guarding with > 0, would cover it, and a one-line test alongside the existing "defaults the node count" case would lock it in.

Nit, take or leave: the schemas advertise every action as available with runtimeRequired: true for create, and the PR body notes create needs the Docker socket work in #154 to actually spawn containers locally. If the runtime without #154 answers create with an error, the adapter surfaces it, so this is fine as is; just flagging in case you would rather mark create with a reason until #154 lands.

Everything else checks out: registration follows the current catalog pattern (adapters plus cloudProxy.ts, no frontend edits needed), the capability claims are backed by real adapter methods, tests assert concrete request paths and bodies rather than mocking everything away, and the README matrix was regenerated. Nice work.

@hectorvent
hectorvent merged commit fd3bd2f into floci-io:main Jul 29, 2026
8 checks passed
TheSaifZaman added a commit to TheSaifZaman/floci-ui that referenced this pull request Jul 29, 2026
GKE gained create and delete in floci-io#155, so 'k8s is read-only on every cloud' is no longer true. The AKS limitation is runtime-specific and stands on its own: floci-az cannot provision a cluster. Also renames a leftover 'machine' variable to 'cluster'.
@hectorvent

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 0.3.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

thomhurst pushed a commit to thomhurst/floci-ui that referenced this pull request Aug 18, 2026
# [0.3.0](floci-io/floci-ui@0.2.0...0.3.0) (2026-08-18)

### Bug Fixes

* **docker:** frontend dev container missing rolldown native binding ([floci-io#152](floci-io#152)) ([a531a1b](floci-io@a531a1b))
* **docker:** init scripts failing on Windows due to CRLF line endings ([floci-io#138](floci-io#138)) ([238e924](floci-io@238e924))
* **docker:** mount the Docker socket so Lambda and Cloud SQL can run ([floci-io#154](floci-io#154)) ([8ee3715](floci-io@8ee3715))
* **frontend:** colour the connection dot from the connection state ([floci-io#181](floci-io#181)) ([0e0682d](floci-io@0e0682d))
* **frontend:** show app-level validation messages in dynamic create form ([floci-io#150](floci-io#150)) ([69ba389](floci-io@69ba389)), closes [floci-io#112](floci-io#112)

### Features

* **api:** derive service availability from a single catalog ([floci-io#153](floci-io#153)) ([2d62143](floci-io@2d62143))
* **aws:** add API Gateway to Cloud Explorer ([floci-io#169](floci-io#169)) ([07fe1c6](floci-io@07fe1c6))
* **aws:** add DynamoDB Cloud Explorer ([floci-io#143](floci-io#143)) ([074eef3](floci-io@074eef3))
* **azure:** add Key Vault explorer ([floci-io#147](floci-io#147)) ([90dd60e](floci-io@90dd60e))
* **compute:** add an Azure Virtual Machines adapter ([floci-io#161](floci-io#161)) ([06541a5](floci-io@06541a5))
* **foundation:** add iac service-type category ([floci-io#178](floci-io#178)) ([c9e9717](floci-io@c9e9717))
* **frontend:** collapsible sidebar with icon rail ([floci-io#180](floci-io#180)) ([2f05f46](floci-io@2f05f46))
* **gcp:** add Cloud SQL and GKE adapters ([floci-io#155](floci-io#155)) ([fd3bd2f](floci-io@fd3bd2f))
* **release:** one-button release cut from main ([floci-io#187](floci-io#187)) ([d7e940b](floci-io@d7e940b))
* **s3:** add inline preview for images, video, audio and text objects ([floci-io#177](floci-io#177)) ([8b945fd](floci-io@8b945fd))
* **serverless:** Add loading, empty, and retry states to Azure Functions view ([floci-io#136](floci-io#136)) ([c4bd78f](floci-io@c4bd78f)), closes [floci-io#114](floci-io#114)
* **serverless:** improve Azure Functions metadata [floci-io#113](floci-io#113) ([floci-io#140](floci-io#140)) ([bcd21a3](floci-io@bcd21a3))
fredpena added a commit that referenced this pull request Aug 30, 2026
Split out of #155 so each service lands on its own. Independent of #155
and #156 — this branch is off `main`.

The sidebar carried a route-less **"Queue" placeholder that could never
light up**, while Floci core has had three seeded SQS queues the whole
time:

```
$ curl -s .../aws/services/messaging/resources | jq -r '.[]|"\(.name) msgs=\(.metadata.approximateMessages)"'
orders-queue msgs=0
dead-letter-queue msgs=0
notifications-queue msgs=0
```

One category for both SQS and Pub/Sub rather than separate queue/topic
ones: the delivery semantics differ, but a console renders both the same
way — a named endpoint with a depth and a few settings — so splitting
them would double the nav for nothing.

## Contract details worth a look

- **SQS ids.** SQS addresses queues by URL, but a URL embeds the
endpoint and changes if the runtime is re-pointed, which makes it a poor
stable id. The adapter uses the queue name and resolves it via
`GetQueueUrl` per call, as the AWS console does. Epoch-second timestamps
are converted to the ISO strings the contract expects.
- **FIFO.** `Attributes.FifoQueue=true` is set for a `.fifo` name. Worth
calling out because *neither* layer of verification caught its earlier
absence: the unit stub accepted any input, and Floci core infers FIFO
from the suffix so it worked locally too. It would only have failed
against AWS. Caught in review on #155 and fixed here.
- **Pub/Sub creates with `PUT`** on the resource path, not `POST` to the
collection.
- A queue whose `GetQueueAttributes` fails still lists, with detail
omitted — a describe failure should degrade one row, not blank the
table.

## One SPI change

`CloudResource.type` was a closed union of eleven literals; `queue`,
`fifo-queue` and `topic` are the first additions since. It is now open
with a `KnownResourceType` alias documenting the convention — nothing
dispatches exhaustively on it, so a closed union meant editing two
packages per adapter for no safety. `CloudServiceType` stays closed,
because that one is route-addressable and a typo there should 404.

The identical widening also appears on #156, so whichever lands second
is a no-op for that hunk.

Adds `@aws-sdk/client-sqs` (both `bun.lock` and `pnpm-lock.yaml` updated
— the API installs with `bun --frozen-lockfile`, which I learned the
hard way).

## Verification

`pnpm lint`, `type-check`, `test`, `build` pass. Live round-trip on both
providers:

```
$ curl -X POST .../aws/services/messaging/resources -d '{"queueName":"probe","visibilityTimeout":"45"}'
  create: 201 → inspect: vis=45 arn=arn:aws:sqs:us-east-1:000000000000:probe → delete: 200 → 404

$ curl -X POST .../gcp/services/messaging/resources -d '{"topicName":"probe"}'
  create: 201 → list: [('probe','topic')] → delete: 200 → []
```

README service matrix regenerated from the registry.

## Type of change

- [ ] Bug fix (`fix:`)
- [x] New feature / service UI (`feat:`)
- [ ] Breaking change (`feat!:` or `fix!:`)
- [ ] Docs / chore

## Area

- [ ] Frontend (`packages/frontend`)
- [x] API / Cloud Proxy (`packages/api`)
- [x] Cloud Explorer adapter / schema
- [ ] Build / CI / Docker

## Checklist

- [x] `pnpm lint`, `pnpm type-check`, `pnpm test`, and `pnpm build` pass
locally
- [x] New or updated tests added where it makes sense (`bun test` in
`packages/api`)
- [x] No fake/mock data added — unwired states stay empty or show an
explicit placeholder
- [x] Commit messages / PR title follow [Conventional
Commits](https://www.conventionalcommits.org/)

---------

Co-authored-by: fredpena <f.ant.pena@gmail.com>
fredpena pushed a commit to TheSaifZaman/floci-ui that referenced this pull request Sep 1, 2026
# [0.4.0](floci-io/floci-ui@0.3.0...0.4.0) (2026-09-01)

### Bug Fixes

* **ec2:** include catalog AMIs in launch selector ([floci-io#191](floci-io#191)) ([b72135d](floci-io@b72135d))

### Features

* **aws:** add CloudFormation adapter to Cloud Explorer ([floci-io#184](floci-io#184)) ([f3d6105](floci-io@f3d6105)), closes [floci-io#81](floci-io#81) [floci-io#75](floci-io#75) [floci-io#81](floci-io#81) [floci-io#75](floci-io#75) [floci-io#81](floci-io#81)
* **aws:** add EventBridge explorer ([floci-io#146](floci-io#146)) ([42944e9](floci-io@42944e9)), closes [floci-io#85](floci-io#85)
* **aws:** add IAM to Cloud Explorer ([floci-io#145](floci-io#145)) ([fc50d19](floci-io@fc50d19)), closes [floci-io#79](floci-io#79)
* **aws:** add Secrets Manager resource adapter ([floci-io#193](floci-io#193)) ([4811866](floci-io@4811866))
* **azure:** add databases and split Cosmos NoSQL ([floci-io#149](floci-io#149)) ([2e704f4](floci-io@2e704f4)), closes [floci-io#92](floci-io#92) [floci-io#67](floci-io#67) [floci-io/floci-az#138](floci-io/floci-az#138) [floci-io#143](floci-io#143)
* **azure:** add Service Bus explorer ([floci-io#144](floci-io#144)) ([a9f0d06](floci-io@a9f0d06)), closes [floci-io#89](floci-io#89)
* **eks:** Manage nodegroups and Fargate profiles via Cloud Proxy ([floci-io#194](floci-io#194)) ([3091cc9](floci-io@3091cc9)), closes [floci-io#106](floci-io#106)
* **loadbalancing:** add an AWS Elastic Load Balancing adapter ([floci-io#168](floci-io#168)) ([10d4298](floci-io@10d4298)), closes [floci-io#162](floci-io#162) [floci-io#162](floci-io#162) [floci-io#156](floci-io#156)
* **messaging:** add a messaging category with SQS and Pub/Sub ([floci-io#157](floci-io#157)) ([dfa6d1c](floci-io@dfa6d1c)), closes [floci-io#155](floci-io#155) [floci-io#155](floci-io#155) [floci-io#156](floci-io#156) [floci-io#156](floci-io#156)
* **secretsmanager:** add JSON key-value editor for secret values ([floci-io#195](floci-io#195)) ([8e88961](floci-io@8e88961)), closes [floci-io#151](floci-io#151)
* **ses:** Add AWS SES mailbox to Cloud Explorer ([floci-io#196](floci-io#196)) ([6389a56](floci-io@6389a56)), closes [floci-io#130](floci-io#130)
fredpena added a commit that referenced this pull request Sep 3, 2026
… Manager (#156)

Narrowed: this is now **secrets only**, off `main`. Cloud SQL/GKE are
#155 and messaging is #157 — all three independent.

Both runtimes serve secret metadata, but the console had only an
AWS-specific page and nothing for GCP.

| Cloud | Was | Now |
|---|---|---|
| AWS Secrets Manager | dedicated page outside Cloud Explorer | SPI
adapter; page retained for value reveal |
| GCP Secret Manager | not present | list, create, inspect, delete |

## No secret value reaches a resource object

Neither adapter reads a value and no schema returns one. A value on
`CloudResource.metadata` would flow into the inspector, the client-side
query cache and the request telemetry — reveal has to be an explicit,
uncached action.

Both test files assert this rather than trusting the implementation:

```ts
// AWS: GetSecretValue is never sent, and no value-shaped key survives
expect(sent.every((c) => c.constructor.name !== 'GetSecretValueCommand')).toBe(true)
for (const key of Object.keys(resource.metadata)) expect(key.toLowerCase()).not.toContain('value')

// GCP: reading a payload needs versions/latest:access — never requested
expect(calls.every((c) => !c.url.includes(':access'))).toBe(true)
```

## On the create-payload review comment

Half right, and the useful half is now fixed.

The premise isn't: AWS marks both `SecretString` and `SecretBinary`
**optional** on `CreateSecret`, and a valueless create succeeds against
the runtime too —

```
$ curl -X POST .../aws/services/secrets/resources -d '{"secretName":"floci-noval"}'
  create: 201  → exists: floci-noval
```

— so create wasn't failing and the matrix wasn't wrong. But a secret you
can't put a value in is close to useless, and the schema offered no way
to supply one. Create now accepts an optional `secretValue` and forwards
it once. That direction is safe: input never lands on a resource, and
there's a test asserting the value does not appear in the returned
object.

## `routeByCloud`

New catalog field, and the part I'd most like a second opinion on.

AWS keeps its dedicated page because that's still the only way to read a
value; GCP goes through the generic explorer. A single `route` per
catalog entry can't express that, and pointing GCP at an AWS-only page
would be worse. So the entry carries `routeByCloud: {aws:
'/secretsmanager'}`, and the override disappears when the page migrates.

I considered migrating the AWS page here instead, but that drops value
reveal — a real regression — until the row-action mechanism exists. This
felt like the honest intermediate rather than a silent capability loss.

## Small correctness note

AWS delete uses `ForceDeleteWithoutRecovery`. Without it the secret
enters a 30-day recovery window and keeps appearing in the list after
the user deleted it, which reads as a broken delete.

## Overlap to be aware of

`CloudResource.type` is widened identically here and on #157, so
whichever lands second is a no-op for that hunk.

## Verification

`pnpm lint`, `type-check`, `test`, `build` pass. Live round-trip on both
providers, with routing resolving per cloud:

```
aws    Secrets Manager   available   route=/secretsmanager
gcp    Secret Manager    available   route=secrets
azure  Secrets Manager   coming_soon route=secrets
```

## Type of change

- [ ] Bug fix (`fix:`)
- [x] New feature / service UI (`feat:`)
- [ ] Breaking change (`feat!:` or `fix!:`)
- [ ] Docs / chore

## Area

- [ ] Frontend (`packages/frontend`)
- [x] API / Cloud Proxy (`packages/api`)
- [x] Cloud Explorer adapter / schema
- [ ] Build / CI / Docker

## Checklist

- [x] `pnpm lint`, `pnpm type-check`, `pnpm test`, and `pnpm build` pass
locally
- [x] New or updated tests added where it makes sense (`bun test` in
`packages/api`)
- [x] No fake/mock data added
- [x] Commit messages / PR title follow [Conventional
Commits](https://www.conventionalcommits.org/)

---------

Co-authored-by: fredpena <f.ant.pena@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants