@sponson/adapters 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/algolia.d.ts +6 -0
- package/dist/algolia.js +151 -0
- package/dist/algolia.js.map +1 -0
- package/dist/clerk.js +1 -1
- package/dist/clerk.js.map +1 -1
- package/dist/cloudflare.d.ts +25 -0
- package/dist/cloudflare.js +310 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/common.d.ts +2 -6
- package/dist/common.js.map +1 -1
- package/dist/digest.d.ts +46 -0
- package/dist/digest.js +129 -0
- package/dist/digest.js.map +1 -0
- package/dist/digitalocean.d.ts +5 -0
- package/dist/digitalocean.js +243 -0
- package/dist/digitalocean.js.map +1 -0
- package/dist/http-adapter-action.d.ts +63 -0
- package/dist/http-adapter-action.js +369 -0
- package/dist/http-adapter-action.js.map +1 -0
- package/dist/http-adapter-auth.d.ts +88 -0
- package/dist/http-adapter-auth.js +437 -0
- package/dist/http-adapter-auth.js.map +1 -0
- package/dist/http-adapter-client.d.ts +51 -0
- package/dist/http-adapter-client.js +156 -0
- package/dist/http-adapter-client.js.map +1 -0
- package/dist/http-adapter-graphql.d.ts +39 -0
- package/dist/http-adapter-graphql.js +157 -0
- package/dist/http-adapter-graphql.js.map +1 -0
- package/dist/http-adapter-list.d.ts +33 -0
- package/dist/http-adapter-list.js +421 -0
- package/dist/http-adapter-list.js.map +1 -0
- package/dist/http-adapter-resource.d.ts +29 -0
- package/dist/http-adapter-resource.js +462 -0
- package/dist/http-adapter-resource.js.map +1 -0
- package/dist/http-adapter-spec.d.ts +216 -0
- package/dist/http-adapter-spec.js +660 -0
- package/dist/http-adapter-spec.js.map +1 -0
- package/dist/http-adapter.d.ts +16 -0
- package/dist/http-adapter.js +28 -0
- package/dist/http-adapter.js.map +1 -0
- package/dist/http.d.ts +61 -2
- package/dist/http.js +79 -18
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.js +24 -2
- package/dist/index.js.map +1 -1
- package/dist/launchdarkly.d.ts +15 -0
- package/dist/launchdarkly.js +337 -0
- package/dist/launchdarkly.js.map +1 -0
- package/dist/manual.d.ts +13 -0
- package/dist/manual.js +201 -0
- package/dist/manual.js.map +1 -0
- package/dist/neon.js +1 -1
- package/dist/neon.js.map +1 -1
- package/dist/netlify.d.ts +18 -0
- package/dist/netlify.js +436 -0
- package/dist/netlify.js.map +1 -0
- package/dist/planetscale.d.ts +10 -0
- package/dist/planetscale.js +311 -0
- package/dist/planetscale.js.map +1 -0
- package/dist/providers.d.ts +26 -0
- package/dist/providers.js +36 -0
- package/dist/providers.js.map +1 -0
- package/dist/recipes.d.ts +167 -0
- package/dist/recipes.js +246 -0
- package/dist/recipes.js.map +1 -0
- package/dist/secrets.d.ts +44 -0
- package/dist/secrets.js +279 -0
- package/dist/secrets.js.map +1 -1
- package/dist/sigv4.d.ts +56 -0
- package/dist/sigv4.js +118 -0
- package/dist/sigv4.js.map +1 -0
- package/dist/supabase.d.ts +9 -0
- package/dist/supabase.js +385 -0
- package/dist/supabase.js.map +1 -0
- package/dist/vercel.js +1 -1
- package/dist/vercel.js.map +1 -1
- package/dist/xata.d.ts +8 -0
- package/dist/xata.js +142 -0
- package/dist/xata.js.map +1 -0
- package/dist/xml.d.ts +25 -0
- package/dist/xml.js +211 -0
- package/dist/xml.js.map +1 -0
- package/package.json +11 -4
- package/recipes/amplify.yaml +147 -0
- package/recipes/auth0.yaml +178 -0
- package/recipes/azure_swa.yaml +116 -0
- package/recipes/cloud_run.yaml +97 -0
- package/recipes/cloudflare.yaml +108 -0
- package/recipes/cockroachdb.yaml +132 -0
- package/recipes/configcat.yaml +123 -0
- package/recipes/datadog.yaml +136 -0
- package/recipes/firebase.yaml +84 -0
- package/recipes/flagsmith.yaml +98 -0
- package/recipes/fly.yaml +97 -0
- package/recipes/fly_machines.yaml +67 -0
- package/recipes/gcs.yaml +102 -0
- package/recipes/github.yaml +123 -0
- package/recipes/growthbook.yaml +124 -0
- package/recipes/heroku.yaml +98 -0
- package/recipes/honeycomb.yaml +89 -0
- package/recipes/inngest.yaml +97 -0
- package/recipes/kinde.yaml +120 -0
- package/recipes/mongodb_atlas.yaml +119 -0
- package/recipes/okta.yaml +177 -0
- package/recipes/posthog.yaml +127 -0
- package/recipes/postmark.yaml +105 -0
- package/recipes/postmark_server.yaml +93 -0
- package/recipes/prisma.yaml +150 -0
- package/recipes/qstash.yaml +134 -0
- package/recipes/railway.yaml +130 -0
- package/recipes/render.yaml +103 -0
- package/recipes/resend.yaml +130 -0
- package/recipes/s3.yaml +108 -0
- package/recipes/sendgrid.yaml +165 -0
- package/recipes/sentry.yaml +158 -0
- package/recipes/split.yaml +121 -0
- package/recipes/statsig.yaml +124 -0
- package/recipes/stripe.yaml +310 -0
- package/recipes/stytch.yaml +113 -0
- package/recipes/svix.yaml +109 -0
- package/recipes/turso.yaml +98 -0
- package/recipes/unleash.yaml +149 -0
- package/recipes/upstash.yaml +130 -0
- package/recipes/vercel.yaml +116 -0
- package/recipes/workos.yaml +70 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Cloudflare API v4 recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: cloudflare
|
|
4
|
+
title: Cloudflare
|
|
5
|
+
category: dns
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: Create DNS record
|
|
9
|
+
url: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/
|
|
10
|
+
- title: List DNS records
|
|
11
|
+
url: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/list/
|
|
12
|
+
- title: DNS record details
|
|
13
|
+
url: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/get/
|
|
14
|
+
- title: Update DNS record (PATCH)
|
|
15
|
+
url: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/edit/
|
|
16
|
+
- title: Delete DNS record
|
|
17
|
+
url: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/delete/
|
|
18
|
+
api:
|
|
19
|
+
base_url: https://api.cloudflare.com/client/v4
|
|
20
|
+
base_url_env: CLOUDFLARE_API_URL
|
|
21
|
+
auth: { bearer_env: CLOUDFLARE_API_TOKEN }
|
|
22
|
+
assumptions:
|
|
23
|
+
- id: CF1
|
|
24
|
+
verified: true
|
|
25
|
+
text: "Records are created with `POST /zones/{zone_id}/dns_records` (`type`, `name`, `content`, `ttl`, `proxied`, `comment`), authenticated with an API token as `Authorization: Bearer` that has DNS Write on the zone."
|
|
26
|
+
source: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/
|
|
27
|
+
- id: CF2
|
|
28
|
+
verified: true
|
|
29
|
+
text: "`GET /zones/{zone_id}/dns_records` answers `{ result: [...] }` and filters by `type` and `name.exact` (names compare case-insensitively)."
|
|
30
|
+
source: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/list/
|
|
31
|
+
- id: CF3
|
|
32
|
+
verified: true
|
|
33
|
+
text: "Single-record answers (create, details, update) carry the record under `result`, with its `id`."
|
|
34
|
+
source: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/get/
|
|
35
|
+
- id: CF4
|
|
36
|
+
verified: true
|
|
37
|
+
text: "`PATCH /zones/{zone_id}/dns_records/{id}` updates a record; `DELETE` on the same path removes it permanently."
|
|
38
|
+
source: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/delete/
|
|
39
|
+
- id: CF5
|
|
40
|
+
verified: false
|
|
41
|
+
text: "A PATCH needs `name` and `type` alongside the changed fields (the edit schema does not mark them optional), so every update sends both."
|
|
42
|
+
source: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/edit/
|
|
43
|
+
- id: CF6
|
|
44
|
+
verified: false
|
|
45
|
+
text: "The API returns `name` lower-cased as the full name and `content` as written, so `name` must be given lower-case and fully qualified, or every plan finds no record and tries to create one."
|
|
46
|
+
- id: CF7
|
|
47
|
+
verified: false
|
|
48
|
+
text: "A proxied record reports `ttl: 1` (automatic) whatever was sent, so `ttl` other than 1 with `proxied: true` shows as drift on every plan."
|
|
49
|
+
- id: CF8
|
|
50
|
+
verified: true
|
|
51
|
+
text: A CNAME cannot share its name with another record, so name and type identify it within the zone and a filtered list holds at most one, on its first page.
|
|
52
|
+
source: https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/
|
|
53
|
+
ops:
|
|
54
|
+
dns_cname:
|
|
55
|
+
kind: resource
|
|
56
|
+
title: DNS CNAME record
|
|
57
|
+
summary: A CNAME record in a zone, such as `pr-42.preview.example.com` pointing at the preview deployment's host. Located by name and type; a console edit of its target, proxying, TTL or comment is drift.
|
|
58
|
+
covers: [cloudflare-dns]
|
|
59
|
+
params:
|
|
60
|
+
zone_id:
|
|
61
|
+
type: string
|
|
62
|
+
required: true
|
|
63
|
+
pattern: "^[0-9a-f]{32}$"
|
|
64
|
+
description: The zone's id (32 hex characters, on the zone's Overview page).
|
|
65
|
+
example: 023e105f4ecef8ad9ca31a8372d0c353
|
|
66
|
+
name:
|
|
67
|
+
type: string
|
|
68
|
+
required: true
|
|
69
|
+
pattern: "^[a-z0-9*_.-]+$"
|
|
70
|
+
description: The record's full name, lower-case, zone included.
|
|
71
|
+
example: "${ctx.scope}.preview.example.com"
|
|
72
|
+
target:
|
|
73
|
+
type: string
|
|
74
|
+
required: true
|
|
75
|
+
description: The host the name points at (the record's `content`).
|
|
76
|
+
example: preview-host.example.net
|
|
77
|
+
proxied:
|
|
78
|
+
type: boolean
|
|
79
|
+
default: false
|
|
80
|
+
description: Whether Cloudflare proxies the traffic.
|
|
81
|
+
ttl:
|
|
82
|
+
type: integer
|
|
83
|
+
default: 1
|
|
84
|
+
description: TTL in seconds (60–86400), or 1 for automatic.
|
|
85
|
+
comment:
|
|
86
|
+
type: string
|
|
87
|
+
description: A note on the record; no effect on DNS.
|
|
88
|
+
example: Managed by Sponson
|
|
89
|
+
http:
|
|
90
|
+
find:
|
|
91
|
+
path: "/zones/{zone_id}/dns_records?type=CNAME&name.exact={name}"
|
|
92
|
+
list_path: /result
|
|
93
|
+
match: { type: CNAME, name: { param: name } }
|
|
94
|
+
create: { path: "/zones/{zone_id}/dns_records" }
|
|
95
|
+
update:
|
|
96
|
+
method: PATCH
|
|
97
|
+
path: "/zones/{zone_id}/dns_records/{id}"
|
|
98
|
+
body: { type: CNAME, name: { param: name } }
|
|
99
|
+
delete: { path: "/zones/{zone_id}/dns_records/{id}" }
|
|
100
|
+
item_path: /result
|
|
101
|
+
fields:
|
|
102
|
+
content: { param: target }
|
|
103
|
+
proxied: { param: proxied }
|
|
104
|
+
ttl: { param: ttl }
|
|
105
|
+
comment: { param: comment }
|
|
106
|
+
outputs: { hostname: /name }
|
|
107
|
+
live:
|
|
108
|
+
params: { zone_id: SPONSON_LIVE_CLOUDFLARE_ZONE_ID, name: SPONSON_LIVE_CLOUDFLARE_NAME }
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# CockroachDB Cloud API recipes (service account API key, bearer). Format and checklist: docs/adr/0020-recipes.md,
|
|
3
|
+
# CONTRIBUTING.md "Adding a recipe".
|
|
4
|
+
provider: cockroachdb
|
|
5
|
+
title: CockroachDB Cloud
|
|
6
|
+
category: databases
|
|
7
|
+
verified_on: "2026-10-11"
|
|
8
|
+
docs:
|
|
9
|
+
- title: Cloud API OpenAPI document (version 2026-09-15)
|
|
10
|
+
url: https://cockroachlabs.cloud/assets/docs/api/latest/openapi.json
|
|
11
|
+
- title: Use the CockroachDB Cloud API
|
|
12
|
+
url: https://docs.cockroachlabs.com/docs/cockroachcloud/cloud-api
|
|
13
|
+
api:
|
|
14
|
+
base_url: https://cockroachlabs.cloud/api/v1
|
|
15
|
+
base_url_env: COCKROACH_API_URL
|
|
16
|
+
auth: { bearer_env: COCKROACH_API_KEY }
|
|
17
|
+
headers: { Cc-Version: "2024-09-16" }
|
|
18
|
+
detect:
|
|
19
|
+
env: ["COCKROACH_*"]
|
|
20
|
+
db_hosts: [.cockroachlabs.cloud]
|
|
21
|
+
starter:
|
|
22
|
+
- op: database
|
|
23
|
+
values: { name: "app_${ctx.scope}" }
|
|
24
|
+
where:
|
|
25
|
+
cluster_id: "CockroachDB Cloud Console → your cluster (the UUID in its URL), or `ccloud cluster list`"
|
|
26
|
+
assumptions:
|
|
27
|
+
- id: CR1
|
|
28
|
+
verified: true
|
|
29
|
+
text: "The Cloud API authenticates with a service account's secret key as `Authorization: Bearer`; the key has the service account's roles."
|
|
30
|
+
source: https://docs.cockroachlabs.com/docs/cockroachcloud/cloud-api
|
|
31
|
+
- id: CR2
|
|
32
|
+
verified: true
|
|
33
|
+
text: "`Cc-Version` pins the API version (`YYYY-MM-DD`); without it the latest version answers, which may change under a client. The guide documents `2024-09-16`."
|
|
34
|
+
source: https://docs.cockroachlabs.com/docs/cockroachcloud/cloud-api
|
|
35
|
+
- id: CR3
|
|
36
|
+
verified: true
|
|
37
|
+
text: "`POST /clusters/{cluster_id}/databases` with `{ name }` creates a database and answers `{ name, table_count }`; `GET` on the same path lists `{ databases: [{ name, table_count }], pagination: { next_page } }`, paged with `pagination.page`; `DELETE /clusters/{cluster_id}/databases/{name}` deletes one. There is no GET of a single database."
|
|
38
|
+
source: https://cockroachlabs.cloud/assets/docs/api/latest/openapi.json
|
|
39
|
+
- id: CR4
|
|
40
|
+
verified: true
|
|
41
|
+
text: "`POST /clusters/{cluster_id}/sql-users` with `{ name, password }` (both required) creates a SQL user; `GET` on the same path lists `{ users: [{ name }], pagination: { next_page } }`; `DELETE /clusters/{cluster_id}/sql-users/{name}` deletes one. The password cannot be read back; `PUT …/sql-users/{name}/password` changes it."
|
|
42
|
+
source: https://cockroachlabs.cloud/assets/docs/api/latest/openapi.json
|
|
43
|
+
- id: CR5
|
|
44
|
+
verified: true
|
|
45
|
+
text: "A SQL user created through the API gets the SQL `admin` role by default, which the guide advises against for anything but administration."
|
|
46
|
+
source: https://docs.cockroachlabs.com/docs/cockroachcloud/cloud-api
|
|
47
|
+
- id: CR6
|
|
48
|
+
verified: true
|
|
49
|
+
text: "Creating or deleting databases and SQL users needs a cluster-level role of the service account (Cluster Admin, Cluster Operator or Cluster Data Accessor for databases; Cluster Admin for SQL users)."
|
|
50
|
+
source: https://cockroachlabs.cloud/assets/docs/api/latest/openapi.json
|
|
51
|
+
- id: CR7
|
|
52
|
+
verified: false
|
|
53
|
+
text: "`COCKROACH_API_KEY` is the variable the CockroachDB Terraform provider and `ccloud` read the key from."
|
|
54
|
+
- id: CR8
|
|
55
|
+
verified: false
|
|
56
|
+
text: "A second create of an existing database or SQL user is refused with 409 (ALREADY_EXISTS), and deleting one that is gone answers 404."
|
|
57
|
+
- id: CR9
|
|
58
|
+
verified: false
|
|
59
|
+
text: "Deleting a database drops it with its tables (CASCADE); the API offers no way to refuse when it holds data."
|
|
60
|
+
- id: CR10
|
|
61
|
+
verified: false
|
|
62
|
+
text: "The API takes database and user names that need quoting in SQL (`app_pr-42`, from a scope with `-`) and quotes them itself."
|
|
63
|
+
ops:
|
|
64
|
+
database:
|
|
65
|
+
kind: resource
|
|
66
|
+
title: Database in a cluster
|
|
67
|
+
summary: "A database per scope in a shared CockroachDB Cloud cluster, such as `app_pr_42`, instead of a cluster per preview. Located by its name in the cluster's list; only its existence is compared (the API exposes nothing else to set); destroy drops it with its data (CR9)."
|
|
68
|
+
covers: [cockroachdb-database]
|
|
69
|
+
params:
|
|
70
|
+
cluster_id:
|
|
71
|
+
type: string
|
|
72
|
+
required: true
|
|
73
|
+
description: The cluster's id (a UUID, shown in the Cloud Console's URL).
|
|
74
|
+
example: 9e3f1a52-63d1-4a4c-9b8f-2c8b7a0e5d11
|
|
75
|
+
name:
|
|
76
|
+
type: string
|
|
77
|
+
required: true
|
|
78
|
+
pattern: "^[A-Za-z_][A-Za-z0-9_.-]{0,62}$"
|
|
79
|
+
description: "The database's name; its identity. A name with `-` (a scope such as `pr-42`) needs quoting in SQL (CR10)."
|
|
80
|
+
example: "app_${ctx.scope}"
|
|
81
|
+
http:
|
|
82
|
+
find:
|
|
83
|
+
path: "/clusters/{cluster_id}/databases"
|
|
84
|
+
list_path: /databases
|
|
85
|
+
match: { name: { param: name } }
|
|
86
|
+
next: /pagination/next_page
|
|
87
|
+
cursor_param: pagination.page
|
|
88
|
+
create: { path: "/clusters/{cluster_id}/databases" }
|
|
89
|
+
delete: { path: "/clusters/{cluster_id}/databases/{id}" }
|
|
90
|
+
id_path: /name
|
|
91
|
+
sim:
|
|
92
|
+
id_from: name
|
|
93
|
+
live:
|
|
94
|
+
params: { cluster_id: SPONSON_LIVE_COCKROACH_CLUSTER_ID }
|
|
95
|
+
sql_user:
|
|
96
|
+
kind: resource
|
|
97
|
+
title: SQL user in a cluster
|
|
98
|
+
summary: "A SQL user per scope in a shared CockroachDB Cloud cluster, such as `app_pr_42`, with its password as an input (`{ secret: … }`, or a sensitive output of another line), sent on create only and never compared. It gets the SQL `admin` role (CR5): grant narrower privileges in SQL if previews must not administer the cluster. Located by its name; destroy deletes the user."
|
|
99
|
+
covers: []
|
|
100
|
+
params:
|
|
101
|
+
cluster_id:
|
|
102
|
+
type: string
|
|
103
|
+
required: true
|
|
104
|
+
description: The cluster's id (a UUID, shown in the Cloud Console's URL).
|
|
105
|
+
example: 9e3f1a52-63d1-4a4c-9b8f-2c8b7a0e5d11
|
|
106
|
+
name:
|
|
107
|
+
type: string
|
|
108
|
+
required: true
|
|
109
|
+
pattern: "^[A-Za-z_][A-Za-z0-9_.-]{0,62}$"
|
|
110
|
+
description: The user's name; its identity.
|
|
111
|
+
example: "app_${ctx.scope}"
|
|
112
|
+
password:
|
|
113
|
+
type: string
|
|
114
|
+
required: true
|
|
115
|
+
description: "The user's password, as a reference (`{ secret: env://… }`, or `{ from: <line>.<output> }` of a sensitive output); sent on create only (CR4)."
|
|
116
|
+
example: { secret: "env://PREVIEW_DB_PASSWORD" }
|
|
117
|
+
http:
|
|
118
|
+
find:
|
|
119
|
+
path: "/clusters/{cluster_id}/sql-users"
|
|
120
|
+
list_path: /users
|
|
121
|
+
match: { name: { param: name } }
|
|
122
|
+
next: /pagination/next_page
|
|
123
|
+
cursor_param: pagination.page
|
|
124
|
+
create:
|
|
125
|
+
path: "/clusters/{cluster_id}/sql-users"
|
|
126
|
+
body: { password: { param: password } }
|
|
127
|
+
delete: { path: "/clusters/{cluster_id}/sql-users/{id}" }
|
|
128
|
+
id_path: /name
|
|
129
|
+
sim:
|
|
130
|
+
id_from: name
|
|
131
|
+
live:
|
|
132
|
+
params: { cluster_id: SPONSON_LIVE_COCKROACH_CLUSTER_ID }
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# ConfigCat Public Management API recipes. Format and checklist: docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
3
|
+
provider: configcat
|
|
4
|
+
title: ConfigCat
|
|
5
|
+
category: flags
|
|
6
|
+
verified_on: "2026-10-11"
|
|
7
|
+
docs:
|
|
8
|
+
- title: Public Management API
|
|
9
|
+
url: https://api.configcat.com/docs/
|
|
10
|
+
- title: OpenAPI spec (get value v2, replace value v2, targeting rule models)
|
|
11
|
+
url: https://api.configcat.com/docs/v1/swagger.json
|
|
12
|
+
- title: Terraform provider (credential variable names)
|
|
13
|
+
url: https://github.com/configcat/terraform-provider-configcat/blob/main/docs/index.md
|
|
14
|
+
api:
|
|
15
|
+
base_url: https://api.configcat.com
|
|
16
|
+
base_url_env: CONFIGCAT_API_URL
|
|
17
|
+
auth: { basic: { user_env: CONFIGCAT_BASIC_AUTH_USERNAME, password_env: CONFIGCAT_BASIC_AUTH_PASSWORD } }
|
|
18
|
+
detect:
|
|
19
|
+
deps: [configcat-js, configcat-js-ssr, configcat-js-full, configcat-node, configcat-react]
|
|
20
|
+
env: ["CONFIGCAT_*"]
|
|
21
|
+
starter:
|
|
22
|
+
- op: targeting_rule
|
|
23
|
+
values: { match: "${ctx.scope}" }
|
|
24
|
+
where:
|
|
25
|
+
environment_id: "ConfigCat Dashboard → your product → Environments → the preview environment's ID"
|
|
26
|
+
setting_id: "ConfigCat Public Management API `GET /v1/configs/{configId}/settings`: the flag's `settingId`"
|
|
27
|
+
assumptions:
|
|
28
|
+
- id: CC1
|
|
29
|
+
verified: true
|
|
30
|
+
text: "The API is at `https://api.configcat.com`, authenticated with Basic auth from Public API credentials (the Terraform provider's `CONFIGCAT_BASIC_AUTH_USERNAME` / `CONFIGCAT_BASIC_AUTH_PASSWORD`)."
|
|
31
|
+
source: https://api.configcat.com/docs/v1/swagger.json
|
|
32
|
+
- id: CC2
|
|
33
|
+
verified: true
|
|
34
|
+
text: "`GET /v2/environments/{environmentId}/settings/{settingId}/value` answers the setting's value in the environment bare: `defaultValue`, `targetingRules`, `percentageEvaluationAttribute` and read-only fields."
|
|
35
|
+
source: https://api.configcat.com/docs/v1/swagger.json
|
|
36
|
+
- id: CC3
|
|
37
|
+
verified: true
|
|
38
|
+
text: "`PUT` on the same path replaces the value: only `defaultValue`, `targetingRules` and `percentageEvaluationAttribute` can be set, and one not sent is reset. So those three are sent, as read, with the rule list changed (`parent.send`)."
|
|
39
|
+
source: https://api.configcat.com/docs/v1/swagger.json
|
|
40
|
+
- id: CC4
|
|
41
|
+
verified: true
|
|
42
|
+
text: "A targeting rule is `{ conditions: [{ userCondition: { comparisonAttribute, comparator, comparisonValue: { stringValue, doubleValue, listValue: [{ value, hint }] } } }], value | percentageOptions }`; rules have no id and are evaluated in order. `isOneOf` and `sensitiveIsOneOf` compare a user attribute with a list."
|
|
43
|
+
source: https://api.configcat.com/docs/v1/swagger.json
|
|
44
|
+
- id: CC5
|
|
45
|
+
verified: true
|
|
46
|
+
text: "Answers carry every member of a value (`boolValue`, `stringValue`, `intValue`, `doubleValue`, `predefinedVariationId`) and of a comparison value, the unused ones null; the rule is written with the same nulls so that it reads back equal."
|
|
47
|
+
source: https://api.configcat.com/docs/v1/swagger.json
|
|
48
|
+
- id: CC6
|
|
49
|
+
verified: false
|
|
50
|
+
text: "A condition is read back with `segmentCondition` and `prerequisiteFlagCondition` null and each list value's `hint` null, exactly as written; otherwise every plan shows the rule as changed."
|
|
51
|
+
- id: CC7
|
|
52
|
+
verified: false
|
|
53
|
+
text: "In a product with \"Config changes require a reason\" or approvals turned on, the PUT without `reason` / `bypassApproval` is refused (the query parameters are not sent); the apply then fails."
|
|
54
|
+
source: https://api.configcat.com/docs/v1/swagger.json
|
|
55
|
+
ops:
|
|
56
|
+
targeting_rule:
|
|
57
|
+
kind: list_item
|
|
58
|
+
title: Feature flag targeting rule
|
|
59
|
+
summary: "A targeting rule on a boolean feature flag in one environment that serves a value to the preview, such as `IF Preview IS ONE OF [pr-42] THEN true`. Added after the flag's other rules (evaluated in order: an earlier matching rule wins); the default value and the other rules are written back as read. Identified by the matched value; a console edit of its condition or served value is drift. Destroy removes the rule."
|
|
60
|
+
covers: [configcat-rule]
|
|
61
|
+
params:
|
|
62
|
+
environment_id:
|
|
63
|
+
type: string
|
|
64
|
+
required: true
|
|
65
|
+
description: The environment's id (a UUID).
|
|
66
|
+
example: 08d8becf-d4d9-4c66-8b48-6ac74cd95fba
|
|
67
|
+
setting_id:
|
|
68
|
+
type: string
|
|
69
|
+
required: true
|
|
70
|
+
pattern: "^[0-9]+$"
|
|
71
|
+
description: The feature flag's numeric setting id.
|
|
72
|
+
example: "12345"
|
|
73
|
+
attribute:
|
|
74
|
+
type: string
|
|
75
|
+
required: true
|
|
76
|
+
description: The user attribute the rule compares (a custom attribute such as `Preview`, or `Identifier`, `Email`).
|
|
77
|
+
example: Preview
|
|
78
|
+
comparator:
|
|
79
|
+
type: string
|
|
80
|
+
default: isOneOf
|
|
81
|
+
enum: [isOneOf, sensitiveIsOneOf]
|
|
82
|
+
description: "`isOneOf`, or `sensitiveIsOneOf` (hashed in the config JSON)."
|
|
83
|
+
match:
|
|
84
|
+
type: string
|
|
85
|
+
required: true
|
|
86
|
+
description: The attribute value that is the preview; it identifies the rule.
|
|
87
|
+
example: "${ctx.scope}"
|
|
88
|
+
serve:
|
|
89
|
+
type: boolean
|
|
90
|
+
default: true
|
|
91
|
+
description: The value the flag serves to the preview.
|
|
92
|
+
http:
|
|
93
|
+
parent:
|
|
94
|
+
path: "/v2/environments/{environment_id}/settings/{setting_id}/value"
|
|
95
|
+
method: PUT
|
|
96
|
+
send: [defaultValue, percentageEvaluationAttribute]
|
|
97
|
+
list_path: /targetingRules
|
|
98
|
+
key_field: /conditions/0/userCondition/comparisonValue/listValue/0/value
|
|
99
|
+
item:
|
|
100
|
+
conditions:
|
|
101
|
+
- userCondition:
|
|
102
|
+
comparisonAttribute: { param: attribute }
|
|
103
|
+
comparator: { param: comparator }
|
|
104
|
+
comparisonValue:
|
|
105
|
+
stringValue: null
|
|
106
|
+
doubleValue: null
|
|
107
|
+
listValue: [{ value: { param: match }, hint: null }]
|
|
108
|
+
segmentCondition: null
|
|
109
|
+
prerequisiteFlagCondition: null
|
|
110
|
+
value:
|
|
111
|
+
boolValue: { param: serve }
|
|
112
|
+
stringValue: null
|
|
113
|
+
intValue: null
|
|
114
|
+
doubleValue: null
|
|
115
|
+
predefinedVariationId: null
|
|
116
|
+
sim:
|
|
117
|
+
objects:
|
|
118
|
+
"/v2/environments/{environment_id}/settings/{setting_id}/value":
|
|
119
|
+
defaultValue: { boolValue: false, stringValue: null, intValue: null, doubleValue: null, predefinedVariationId: null }
|
|
120
|
+
targetingRules: []
|
|
121
|
+
percentageEvaluationAttribute: null
|
|
122
|
+
live:
|
|
123
|
+
params: { environment_id: SPONSON_LIVE_CONFIGCAT_ENVIRONMENT_ID, setting_id: SPONSON_LIVE_CONFIGCAT_SETTING_ID }
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Datadog API recipes: every request carries the API key and the application key. Format and checklist:
|
|
3
|
+
# docs/adr/0020-recipes.md, CONTRIBUTING.md "Adding a recipe".
|
|
4
|
+
provider: datadog
|
|
5
|
+
title: Datadog
|
|
6
|
+
category: observability
|
|
7
|
+
verified_on: "2026-10-11"
|
|
8
|
+
docs:
|
|
9
|
+
- title: Synthetics API reference
|
|
10
|
+
url: https://docs.datadoghq.com/api/latest/synthetics/
|
|
11
|
+
- title: API authentication (keys, sites)
|
|
12
|
+
url: https://docs.datadoghq.com/api/latest/authentication/
|
|
13
|
+
- title: Datadog API v1 OpenAPI document (datadog-api-client)
|
|
14
|
+
url: https://github.com/DataDog/datadog-api-client-typescript/blob/master/.generator/schemas/v1/openapi.yaml
|
|
15
|
+
api:
|
|
16
|
+
base_url: https://api.datadoghq.com/api/v1
|
|
17
|
+
base_url_env: DATADOG_API_URL
|
|
18
|
+
auth:
|
|
19
|
+
headers:
|
|
20
|
+
- { header: DD-API-KEY, value_env: DD_API_KEY }
|
|
21
|
+
- { header: DD-APPLICATION-KEY, value_env: DD_APP_KEY }
|
|
22
|
+
detect:
|
|
23
|
+
deps: [dd-trace, "@datadog/"]
|
|
24
|
+
env: ["DD_*", "DATADOG_*"]
|
|
25
|
+
starter:
|
|
26
|
+
- op: synthetic_api_test
|
|
27
|
+
preview_url: url
|
|
28
|
+
values: { name: "preview ${ctx.scope}", locations: ["aws:us-east-2"] }
|
|
29
|
+
assumptions:
|
|
30
|
+
- id: DD1
|
|
31
|
+
verified: true
|
|
32
|
+
text: "Requests carry the API key in `DD-API-KEY` and the application key in `DD-APPLICATION-KEY`; Datadog's clients read them from `DD_API_KEY` and `DD_APP_KEY`. Reading needs the application key too."
|
|
33
|
+
source: https://github.com/DataDog/datadog-api-client-typescript/blob/master/.generator/schemas/v1/openapi.yaml
|
|
34
|
+
- id: DD2
|
|
35
|
+
verified: true
|
|
36
|
+
text: "Each Datadog site has its own API host (`https://api.datadoghq.eu`, `https://api.us3.datadoghq.com`, …): outside US1, set `base_url` in the provider block."
|
|
37
|
+
source: https://docs.datadoghq.com/api/latest/authentication/
|
|
38
|
+
- id: DD3
|
|
39
|
+
verified: true
|
|
40
|
+
text: "`POST /synthetics/tests/api` creates an API test from `name`, `type` (`api`), `config` (`request` with `method` and `url`, `assertions`), `locations`, `options` and `message` (all required), with `subtype` (`http`), `status` (`live` or `paused`) and `tags`, answering it with its `public_id`."
|
|
41
|
+
source: https://github.com/DataDog/datadog-api-client-typescript/blob/master/.generator/schemas/v1/openapi.yaml
|
|
42
|
+
- id: DD4
|
|
43
|
+
verified: true
|
|
44
|
+
text: "`GET /synthetics/tests/api/{public_id}` answers one API test; `PUT` on the same path replaces its configuration with a whole test definition."
|
|
45
|
+
source: https://github.com/DataDog/datadog-api-client-typescript/blob/master/.generator/schemas/v1/openapi.yaml
|
|
46
|
+
- id: DD5
|
|
47
|
+
verified: true
|
|
48
|
+
text: "`GET /synthetics/tests` lists every test as `{ tests: [...] }` (`page_size` and `page_number` are optional); `POST /synthetics/tests/delete` with `{ public_ids: [...] }` deletes tests."
|
|
49
|
+
source: https://github.com/DataDog/datadog-api-client-typescript/blob/master/.generator/schemas/v1/openapi.yaml
|
|
50
|
+
- id: DD6
|
|
51
|
+
verified: false
|
|
52
|
+
text: "Without `page_size` the list answers every test of the organisation, and a test name identifies one test (two with one name make `find` refuse with PARAM_INVALID)."
|
|
53
|
+
- id: DD7
|
|
54
|
+
verified: false
|
|
55
|
+
text: "The fields compared (`config.request`, `config.assertions`, `locations`, `options.tick_every`, `message`, `status`, `tags`) are answered as they were sent, in order."
|
|
56
|
+
- id: DD8
|
|
57
|
+
verified: false
|
|
58
|
+
text: "Deleting a test that is already gone answers 404 (destroy treats it as done)."
|
|
59
|
+
- id: DD9
|
|
60
|
+
verified: false
|
|
61
|
+
text: "Deployment events (`datadog-ci deployment mark`, the DORA deployments API) are not a recipe: they are listed with a POST over a time window and cannot be deleted, so a later run could not find the one it made."
|
|
62
|
+
ops:
|
|
63
|
+
synthetic_api_test:
|
|
64
|
+
kind: resource
|
|
65
|
+
title: Synthetic API test against a preview
|
|
66
|
+
summary: "A Synthetic HTTP test per scope that checks the preview's URL from Datadog's locations, such as `preview pr-42` asserting status 200, with its own monitor. Located by its name; a console edit of its request, assertions, locations, frequency, message, status or tags is drift; destroy deletes the test (and its monitor)."
|
|
67
|
+
covers: [datadog-marker]
|
|
68
|
+
params:
|
|
69
|
+
name:
|
|
70
|
+
type: string
|
|
71
|
+
required: true
|
|
72
|
+
description: The test's name; its identity (DD6).
|
|
73
|
+
example: "preview ${ctx.scope}"
|
|
74
|
+
url:
|
|
75
|
+
type: string
|
|
76
|
+
required: true
|
|
77
|
+
pattern: "^https?://\\S+$"
|
|
78
|
+
description: The URL to request (the preview's URL, or a health path on it).
|
|
79
|
+
example: "https://${ctx.scope}.preview.example.app/api/health"
|
|
80
|
+
method:
|
|
81
|
+
type: string
|
|
82
|
+
default: GET
|
|
83
|
+
enum: [GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS]
|
|
84
|
+
description: The HTTP method.
|
|
85
|
+
assertions:
|
|
86
|
+
type: list
|
|
87
|
+
default: [{ type: statusCode, operator: is, target: 200 }]
|
|
88
|
+
description: "The assertions, each `{ type, operator, target }` (`statusCode`, `responseTime`, `body`, `header`)."
|
|
89
|
+
locations:
|
|
90
|
+
type: list
|
|
91
|
+
required: true
|
|
92
|
+
description: "The managed locations to run from, such as `aws:us-east-2` or `aws:eu-central-1`."
|
|
93
|
+
example: ["aws:us-east-2"]
|
|
94
|
+
tick_every:
|
|
95
|
+
type: integer
|
|
96
|
+
default: 300
|
|
97
|
+
description: How often the test runs, in seconds.
|
|
98
|
+
message:
|
|
99
|
+
type: string
|
|
100
|
+
default: Preview check managed by Sponson
|
|
101
|
+
description: The notification message of the test's monitor.
|
|
102
|
+
status:
|
|
103
|
+
type: string
|
|
104
|
+
default: live
|
|
105
|
+
enum: [live, paused]
|
|
106
|
+
description: "`paused` keeps the test without running it."
|
|
107
|
+
tags:
|
|
108
|
+
type: list
|
|
109
|
+
default: ["managed-by:sponson"]
|
|
110
|
+
description: The test's tags.
|
|
111
|
+
http:
|
|
112
|
+
find:
|
|
113
|
+
path: /synthetics/tests
|
|
114
|
+
list_path: /tests
|
|
115
|
+
match: { name: { param: name } }
|
|
116
|
+
read: { path: "/synthetics/tests/api/{id}" }
|
|
117
|
+
create:
|
|
118
|
+
path: /synthetics/tests/api
|
|
119
|
+
body: { type: api, subtype: http }
|
|
120
|
+
update:
|
|
121
|
+
method: PUT
|
|
122
|
+
body: { type: api, subtype: http }
|
|
123
|
+
delete:
|
|
124
|
+
method: POST
|
|
125
|
+
path: /synthetics/tests/delete
|
|
126
|
+
body: { public_ids: ["{id}"] }
|
|
127
|
+
id_path: /public_id
|
|
128
|
+
fields:
|
|
129
|
+
/config/request/method: { param: method }
|
|
130
|
+
/config/request/url: { param: url }
|
|
131
|
+
/config/assertions: { param: assertions }
|
|
132
|
+
locations: { param: locations }
|
|
133
|
+
/options/tick_every: { param: tick_every }
|
|
134
|
+
message: { param: message }
|
|
135
|
+
status: { param: status }
|
|
136
|
+
tags: { param: tags }
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../../schema/recipe.schema.json
|
|
2
|
+
# Firebase Authentication (Identity Toolkit admin API) recipes. Format and checklist: docs/adr/0020-recipes.md,
|
|
3
|
+
# CONTRIBUTING.md "Adding a recipe".
|
|
4
|
+
provider: firebase
|
|
5
|
+
title: Firebase Authentication
|
|
6
|
+
category: auth
|
|
7
|
+
verified_on: "2026-10-11"
|
|
8
|
+
docs:
|
|
9
|
+
- title: Identity Toolkit API v2, projects.getConfig
|
|
10
|
+
url: https://docs.cloud.google.com/identity-platform/docs/reference/rest/v2/projects/getConfig
|
|
11
|
+
- title: Identity Toolkit API v2, projects.updateConfig
|
|
12
|
+
url: https://docs.cloud.google.com/identity-platform/docs/reference/rest/v2/projects/updateConfig
|
|
13
|
+
- title: Identity Toolkit API v2, Config
|
|
14
|
+
url: https://docs.cloud.google.com/identity-platform/docs/reference/rest/v2/Config
|
|
15
|
+
- title: Authenticate for using REST
|
|
16
|
+
url: https://docs.cloud.google.com/docs/authentication/rest
|
|
17
|
+
api:
|
|
18
|
+
base_url: https://identitytoolkit.googleapis.com/admin/v2
|
|
19
|
+
base_url_env: FIREBASE_API_URL
|
|
20
|
+
auth: { command: [gcloud, auth, print-access-token] }
|
|
21
|
+
detect:
|
|
22
|
+
deps: [firebase, firebase-admin]
|
|
23
|
+
env: ["FIREBASE_*"]
|
|
24
|
+
files: [firebase.json, .firebaserc]
|
|
25
|
+
starter:
|
|
26
|
+
- op: authorized_domain
|
|
27
|
+
where:
|
|
28
|
+
project: "`projects.default` in .firebaserc, or `firebase projects:list`"
|
|
29
|
+
domain: "the preview's host name without `https://` (Firebase takes a domain, so a `{ from }` URL cannot be used)"
|
|
30
|
+
assumptions:
|
|
31
|
+
- id: FB1
|
|
32
|
+
verified: true
|
|
33
|
+
text: "`GET https://identitytoolkit.googleapis.com/admin/v2/projects/{project}/config` answers the project's Auth `Config`."
|
|
34
|
+
source: https://docs.cloud.google.com/identity-platform/docs/reference/rest/v2/projects/getConfig
|
|
35
|
+
- id: FB2
|
|
36
|
+
verified: true
|
|
37
|
+
text: "`PATCH …/admin/v2/projects/{project}/config?updateMask=authorizedDomains` updates the config with a `Config` body; fields set in the body but not named in `updateMask` are ignored, so the write changes the authorized domains only. It needs one of the `identitytoolkit`, `firebase` or `cloud-platform` OAuth scopes."
|
|
38
|
+
source: https://docs.cloud.google.com/identity-platform/docs/reference/rest/v2/projects/updateConfig
|
|
39
|
+
- id: FB3
|
|
40
|
+
verified: true
|
|
41
|
+
text: "`authorizedDomains` is a list of strings, the domains authorized for OAuth redirects; the masked field is replaced by the list sent, so the recipe sends the whole list read just before with one domain added or removed."
|
|
42
|
+
source: https://docs.cloud.google.com/identity-platform/docs/reference/rest/v2/Config
|
|
43
|
+
- id: FB4
|
|
44
|
+
verified: true
|
|
45
|
+
text: "`gcloud auth print-access-token` prints an access token for the signed-in credentials, used as `Authorization: Bearer`. With user credentials some APIs also need the quota project in `x-goog-user-project`: add `headers: { x-goog-user-project: <project> }` to the `providers.http.firebase` block (not needed with a service account; a block's headers are part of its identity)."
|
|
46
|
+
source: https://docs.cloud.google.com/docs/authentication/rest
|
|
47
|
+
- id: FB5
|
|
48
|
+
verified: false
|
|
49
|
+
text: "The config has no precondition the update honours (no etag in `Config`): the line locks the project's config (`lockOn`) against other Sponson runs; a console edit made between the read and the write can still be lost."
|
|
50
|
+
- id: FB6
|
|
51
|
+
verified: false
|
|
52
|
+
text: "An authorized domain is a host name without scheme, port or path, and is read back exactly as written."
|
|
53
|
+
- id: FB7
|
|
54
|
+
verified: false
|
|
55
|
+
text: "The same admin v2 config holds the authorized domains of a Firebase Authentication project with or without the Identity Platform upgrade."
|
|
56
|
+
ops:
|
|
57
|
+
authorized_domain:
|
|
58
|
+
kind: list_item
|
|
59
|
+
title: Authorized domain
|
|
60
|
+
summary: "One domain in Firebase Authentication's authorized domains (Authentication, Settings, Authorized domains), which OAuth sign-in redirects and email links require, such as the preview deployment's host. Read-modify-write of the list with `updateMask=authorizedDomains` under a lock on the project's config; removed on destroy; every other domain (localhost, the Firebase hosting domains) is left as it is."
|
|
61
|
+
covers: [firebase-auth-domains]
|
|
62
|
+
params:
|
|
63
|
+
project:
|
|
64
|
+
type: string
|
|
65
|
+
required: true
|
|
66
|
+
description: The Google Cloud / Firebase project id.
|
|
67
|
+
example: demo-project
|
|
68
|
+
domain:
|
|
69
|
+
type: string
|
|
70
|
+
required: true
|
|
71
|
+
pattern: "^[A-Za-z0-9.-]+$"
|
|
72
|
+
description: "The domain, a host name without scheme or path (`pr-42.preview.example.app`, `my-app-git-feat-x.vercel.app`)."
|
|
73
|
+
example: "${ctx.scope}.preview.example.app"
|
|
74
|
+
http:
|
|
75
|
+
parent:
|
|
76
|
+
path: "/projects/{project}/config?updateMask=authorizedDomains"
|
|
77
|
+
read_path: "/projects/{project}/config"
|
|
78
|
+
list_path: /authorizedDomains
|
|
79
|
+
item: { param: domain }
|
|
80
|
+
sim:
|
|
81
|
+
objects:
|
|
82
|
+
"/projects/{project}/config": { name: projects/demo-project/config, authorizedDomains: [localhost, demo-project.firebaseapp.com, demo-project.web.app] }
|
|
83
|
+
live:
|
|
84
|
+
params: { project: SPONSON_LIVE_FIREBASE_PROJECT }
|