@intentius/chant-lexicon-gcp 0.0.15

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.
Files changed (122) hide show
  1. package/dist/integrity.json +36 -0
  2. package/dist/manifest.json +12 -0
  3. package/dist/meta.json +10919 -0
  4. package/dist/rules/gcp-helpers.ts +117 -0
  5. package/dist/rules/hardcoded-project.ts +58 -0
  6. package/dist/rules/hardcoded-region.ts +56 -0
  7. package/dist/rules/public-iam.ts +43 -0
  8. package/dist/rules/wgc101.ts +56 -0
  9. package/dist/rules/wgc102.ts +35 -0
  10. package/dist/rules/wgc103.ts +45 -0
  11. package/dist/rules/wgc104.ts +42 -0
  12. package/dist/rules/wgc105.ts +46 -0
  13. package/dist/rules/wgc106.ts +36 -0
  14. package/dist/rules/wgc107.ts +39 -0
  15. package/dist/rules/wgc108.ts +41 -0
  16. package/dist/rules/wgc109.ts +39 -0
  17. package/dist/rules/wgc110.ts +38 -0
  18. package/dist/rules/wgc111.ts +54 -0
  19. package/dist/rules/wgc112.ts +56 -0
  20. package/dist/rules/wgc113.ts +42 -0
  21. package/dist/rules/wgc201.ts +36 -0
  22. package/dist/rules/wgc202.ts +39 -0
  23. package/dist/rules/wgc203.ts +44 -0
  24. package/dist/rules/wgc204.ts +39 -0
  25. package/dist/rules/wgc301.ts +34 -0
  26. package/dist/rules/wgc302.ts +34 -0
  27. package/dist/rules/wgc303.ts +37 -0
  28. package/dist/skills/chant-gcp-patterns.md +367 -0
  29. package/dist/skills/chant-gcp-security.md +276 -0
  30. package/dist/skills/chant-gcp.md +108 -0
  31. package/dist/types/index.d.ts +26529 -0
  32. package/package.json +35 -0
  33. package/src/actions/index.ts +52 -0
  34. package/src/codegen/docs-cli.ts +7 -0
  35. package/src/codegen/docs.ts +820 -0
  36. package/src/codegen/generate-cli.ts +24 -0
  37. package/src/codegen/generate.ts +252 -0
  38. package/src/codegen/naming.test.ts +49 -0
  39. package/src/codegen/naming.ts +132 -0
  40. package/src/codegen/package.ts +66 -0
  41. package/src/composites/cloud-function.ts +117 -0
  42. package/src/composites/cloud-run-service.ts +124 -0
  43. package/src/composites/cloud-sql-instance.ts +126 -0
  44. package/src/composites/composites.test.ts +432 -0
  45. package/src/composites/gcs-bucket.ts +111 -0
  46. package/src/composites/gke-cluster.ts +125 -0
  47. package/src/composites/index.ts +20 -0
  48. package/src/composites/managed-certificate.ts +79 -0
  49. package/src/composites/private-service.ts +95 -0
  50. package/src/composites/pubsub-pipeline.ts +102 -0
  51. package/src/composites/secure-project.ts +128 -0
  52. package/src/composites/vpc-network.ts +165 -0
  53. package/src/coverage.test.ts +27 -0
  54. package/src/coverage.ts +51 -0
  55. package/src/default-labels.test.ts +111 -0
  56. package/src/default-labels.ts +93 -0
  57. package/src/generated/index.d.ts +26529 -0
  58. package/src/generated/index.ts +1723 -0
  59. package/src/generated/lexicon-gcp.json +10919 -0
  60. package/src/generated/runtime.ts +4 -0
  61. package/src/import/generator.test.ts +125 -0
  62. package/src/import/generator.ts +82 -0
  63. package/src/import/parser.test.ts +167 -0
  64. package/src/import/parser.ts +80 -0
  65. package/src/import/roundtrip.test.ts +66 -0
  66. package/src/index.ts +54 -0
  67. package/src/lint/post-synth/gcp-helpers.ts +117 -0
  68. package/src/lint/post-synth/index.ts +20 -0
  69. package/src/lint/post-synth/post-synth.test.ts +693 -0
  70. package/src/lint/post-synth/wgc101.ts +56 -0
  71. package/src/lint/post-synth/wgc102.ts +35 -0
  72. package/src/lint/post-synth/wgc103.ts +45 -0
  73. package/src/lint/post-synth/wgc104.ts +42 -0
  74. package/src/lint/post-synth/wgc105.ts +46 -0
  75. package/src/lint/post-synth/wgc106.ts +36 -0
  76. package/src/lint/post-synth/wgc107.ts +39 -0
  77. package/src/lint/post-synth/wgc108.ts +41 -0
  78. package/src/lint/post-synth/wgc109.ts +39 -0
  79. package/src/lint/post-synth/wgc110.ts +38 -0
  80. package/src/lint/post-synth/wgc111.ts +54 -0
  81. package/src/lint/post-synth/wgc112.ts +56 -0
  82. package/src/lint/post-synth/wgc113.ts +42 -0
  83. package/src/lint/post-synth/wgc201.ts +36 -0
  84. package/src/lint/post-synth/wgc202.ts +39 -0
  85. package/src/lint/post-synth/wgc203.ts +44 -0
  86. package/src/lint/post-synth/wgc204.ts +39 -0
  87. package/src/lint/post-synth/wgc301.ts +34 -0
  88. package/src/lint/post-synth/wgc302.ts +34 -0
  89. package/src/lint/post-synth/wgc303.ts +37 -0
  90. package/src/lint/rules/hardcoded-project.ts +58 -0
  91. package/src/lint/rules/hardcoded-region.ts +56 -0
  92. package/src/lint/rules/index.ts +3 -0
  93. package/src/lint/rules/public-iam.ts +43 -0
  94. package/src/lint/rules/rules.test.ts +63 -0
  95. package/src/lsp/completions.test.ts +67 -0
  96. package/src/lsp/completions.ts +17 -0
  97. package/src/lsp/hover.test.ts +66 -0
  98. package/src/lsp/hover.ts +54 -0
  99. package/src/package-cli.ts +24 -0
  100. package/src/plugin.test.ts +250 -0
  101. package/src/plugin.ts +405 -0
  102. package/src/pseudo.test.ts +40 -0
  103. package/src/pseudo.ts +19 -0
  104. package/src/serializer.test.ts +250 -0
  105. package/src/serializer.ts +232 -0
  106. package/src/skills/chant-gcp-patterns.md +367 -0
  107. package/src/skills/chant-gcp-security.md +276 -0
  108. package/src/skills/chant-gcp.md +108 -0
  109. package/src/spec/fetch.test.ts +16 -0
  110. package/src/spec/fetch.ts +121 -0
  111. package/src/spec/parse.test.ts +163 -0
  112. package/src/spec/parse.ts +432 -0
  113. package/src/testdata/compute-instance.yaml +93 -0
  114. package/src/testdata/iam-policy-member.yaml +66 -0
  115. package/src/testdata/manifests/compute-instance.yaml +18 -0
  116. package/src/testdata/manifests/full-app.yaml +34 -0
  117. package/src/testdata/manifests/storage-bucket.yaml +12 -0
  118. package/src/testdata/storage-bucket.yaml +100 -0
  119. package/src/validate-cli.ts +13 -0
  120. package/src/validate.test.ts +38 -0
  121. package/src/validate.ts +30 -0
  122. package/src/variables.ts +15 -0
@@ -0,0 +1,820 @@
1
+ /**
2
+ * GCP Config Connector documentation generator.
3
+ *
4
+ * Produces a standalone Starlight docs site at lexicons/gcp/docs/.
5
+ */
6
+
7
+ import { dirname, join } from "path";
8
+ import { fileURLToPath } from "url";
9
+ import { docsPipeline, writeDocsSite, type DocsConfig } from "@intentius/chant/codegen/docs";
10
+
11
+ /**
12
+ * Extract service name from GCP resource type: "GCP::Compute::Instance" → "Compute"
13
+ */
14
+ function serviceFromType(resourceType: string): string {
15
+ const parts = resourceType.split("::");
16
+ return parts.length >= 2 ? parts[1] : "Other";
17
+ }
18
+
19
+ const overview = `The **GCP Config Connector** lexicon provides full support for defining Google Cloud infrastructure using chant's declarative TypeScript syntax. Resources are serialized to Config Connector YAML manifests.
20
+
21
+ This lexicon is generated from the official [Config Connector CRDs](https://github.com/GoogleCloudPlatform/k8s-config-connector) and includes coverage for 300+ resource types across 80+ GCP services.
22
+
23
+ New? Start with the [Getting Started](/chant/lexicons/gcp/getting-started/) guide.
24
+
25
+ Install it with:
26
+
27
+ \`\`\`bash
28
+ npm install --save-dev @intentius/chant-lexicon-gcp
29
+ \`\`\`
30
+
31
+ ## Quick Start
32
+
33
+ \`\`\`typescript
34
+ import { StorageBucket, IAMPolicyMember, GCP } from "@intentius/chant-lexicon-gcp";
35
+ import { defaultAnnotations } from "@intentius/chant-lexicon-gcp";
36
+
37
+ export const annotations = defaultAnnotations({
38
+ "cnrm.cloud.google.com/project-id": GCP.ProjectId,
39
+ });
40
+
41
+ export const bucket = new StorageBucket({
42
+ location: "US",
43
+ storageClass: "STANDARD",
44
+ uniformBucketLevelAccess: true,
45
+ versioning: { enabled: true },
46
+ });
47
+ \`\`\`
48
+
49
+ The lexicon provides **300+ resource types** across Compute, Storage, IAM, Networking, Container, SQL, PubSub, and more, plus composites (GkeCluster, CloudRunService, CloudSqlInstance, GcsBucket, VpcNetwork, PubSubPipeline, CloudFunctionWithTrigger, PrivateService, ManagedCertificate, SecureProject) for common patterns.
50
+ `;
51
+
52
+ const outputFormat = `The GCP lexicon serializes resources into **Config Connector YAML manifests** (Kubernetes CRDs).
53
+
54
+ ## Building
55
+
56
+ Run \`chant build\` to produce Config Connector YAML from your declarations:
57
+
58
+ \`\`\`bash
59
+ chant build
60
+ # Writes dist/manifests.yaml
61
+ \`\`\`
62
+
63
+ The generated manifests include:
64
+
65
+ - \`apiVersion\` and \`kind\` (Config Connector CRD)
66
+ - \`metadata\` with name, labels, and annotations
67
+ - \`spec\` with the resource configuration
68
+
69
+ ## Key conversions
70
+
71
+ | Chant (TypeScript) | YAML output | Rule |
72
+ |--------------------|-------------|------|
73
+ | \`export const myBucket = new StorageBucket({...})\` | \`metadata.name: my-bucket\` | Export name → kebab-case |
74
+ | \`defaultLabels({...})\` | Merged into all resources | Project-wide label injection |
75
+ | \`defaultAnnotations({...})\` | Merged into all resources | Project-wide annotation injection |
76
+
77
+ ## Applying
78
+
79
+ Apply to a Kubernetes cluster with Config Connector installed:
80
+
81
+ \`\`\`bash
82
+ # Dry run
83
+ kubectl apply -f dist/manifests.yaml --dry-run=server
84
+
85
+ # Apply
86
+ kubectl apply -f dist/manifests.yaml
87
+ \`\`\`
88
+
89
+ ## Compatibility
90
+
91
+ The output is compatible with:
92
+ - kubectl apply/diff
93
+ - Config Connector controller on GKE
94
+ - ArgoCD / Flux GitOps controllers
95
+ - Kustomize (as a base)`;
96
+
97
+ /**
98
+ * Generate documentation for the GCP Config Connector lexicon.
99
+ */
100
+ export async function generateDocs(opts?: { verbose?: boolean }): Promise<void> {
101
+ const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
102
+
103
+ const config: DocsConfig = {
104
+ name: "gcp",
105
+ displayName: "GCP Config Connector",
106
+ description: "Typed constructors for GCP Config Connector resource manifests",
107
+ distDir: join(pkgDir, "dist"),
108
+ outDir: join(pkgDir, "docs"),
109
+ overview,
110
+ outputFormat,
111
+ serviceFromType,
112
+ srcDir: join(pkgDir, "src"),
113
+ basePath: "/chant/lexicons/gcp/",
114
+ extraPages: [
115
+ {
116
+ slug: "getting-started",
117
+ title: "Getting Started",
118
+ description: "Install chant and deploy your first GCP resource in 5 minutes",
119
+ content: `## What is chant?
120
+
121
+ Chant is a TypeScript-to-YAML compiler. You write typed TypeScript declarations, and chant outputs Config Connector YAML manifests that can be applied to a GKE cluster with Config Connector installed.
122
+
123
+ ## Prerequisites
124
+
125
+ 1. A GKE cluster with [Config Connector](https://cloud.google.com/config-connector/docs/overview) installed
126
+ 2. A \`ConfigConnectorContext\` resource configured per namespace
127
+ 3. A GCP Service Account bound to the Config Connector controller
128
+
129
+ ## Install
130
+
131
+ \`\`\`bash
132
+ npm install --save-dev @intentius/chant @intentius/chant-lexicon-gcp
133
+ \`\`\`
134
+
135
+ ## Your first resource
136
+
137
+ The fastest path is the **GcsBucket** composite — one function call that produces a properly configured Storage bucket:
138
+
139
+ \`\`\`typescript
140
+ // src/infra.gcp.ts
141
+ import { GcsBucket } from "@intentius/chant-lexicon-gcp";
142
+ import { defaultAnnotations, GCP } from "@intentius/chant-lexicon-gcp";
143
+
144
+ export const annotations = defaultAnnotations({
145
+ "cnrm.cloud.google.com/project-id": GCP.ProjectId,
146
+ });
147
+
148
+ const { bucket } = GcsBucket({
149
+ name: "my-data-bucket",
150
+ location: "US",
151
+ versioning: true,
152
+ });
153
+
154
+ export { bucket };
155
+ \`\`\`
156
+
157
+ ## Build and deploy
158
+
159
+ \`\`\`bash
160
+ # Generate Config Connector YAML
161
+ chant build --output dist/manifests.yaml
162
+
163
+ # Validate against the cluster API (no changes applied)
164
+ kubectl apply -f dist/manifests.yaml --dry-run=server
165
+
166
+ # Apply
167
+ kubectl apply -f dist/manifests.yaml
168
+ \`\`\`
169
+
170
+ ## Using resource constructors
171
+
172
+ \`\`\`typescript
173
+ import { StorageBucket, IAMPolicyMember, GCP } from "@intentius/chant-lexicon-gcp";
174
+
175
+ export const bucket = new StorageBucket({
176
+ location: "US",
177
+ storageClass: "STANDARD",
178
+ uniformBucketLevelAccess: true,
179
+ versioning: { enabled: true },
180
+ });
181
+
182
+ export const reader = new IAMPolicyMember({
183
+ member: "serviceAccount:app@my-project.iam.gserviceaccount.com",
184
+ role: "roles/storage.objectViewer",
185
+ resourceRef: {
186
+ apiVersion: "storage.cnrm.cloud.google.com/v1beta1",
187
+ kind: "StorageBucket",
188
+ name: bucket,
189
+ },
190
+ });
191
+ \`\`\`
192
+
193
+ ## Next steps
194
+
195
+ - [Config Connector Concepts](/chant/lexicons/gcp/config-connector-concepts/) — resource structure, references, project binding
196
+ - [Examples](/chant/lexicons/gcp/examples/) — StorageBucket, ComputeInstance, CloudSQL, IAM
197
+ - [Lint Rules](/chant/lexicons/gcp/lint-rules/) — built-in checks for security and best practices`,
198
+ },
199
+ {
200
+ slug: "config-connector-concepts",
201
+ title: "Config Connector Concepts",
202
+ description: "Resource structure, resourceRef, project binding, reconciliation lifecycle",
203
+ content: `Every exported resource declaration becomes a Config Connector manifest document in the generated YAML.
204
+
205
+ ## Resource structure
206
+
207
+ Every Config Connector resource has four standard fields:
208
+
209
+ | Field | Source | Example |
210
+ |-------|--------|---------|
211
+ | \`apiVersion\` | Resolved from resource type | \`storage.cnrm.cloud.google.com/v1beta1\` |
212
+ | \`kind\` | Resolved from resource type | \`StorageBucket\` |
213
+ | \`metadata\` | From \`metadata\` property | \`{ name: "my-bucket", labels: {...} }\` |
214
+ | \`spec\` | From remaining props | Resource-specific configuration |
215
+
216
+ ## Resource references
217
+
218
+ Config Connector resources reference each other using \`resourceRef\`:
219
+
220
+ \`\`\`yaml
221
+ # By name (same namespace)
222
+ resourceRef:
223
+ name: my-network
224
+
225
+ # By external reference (cross-project)
226
+ resourceRef:
227
+ external: projects/my-project/global/networks/my-network
228
+ \`\`\`
229
+
230
+ In chant, resource references resolve automatically:
231
+
232
+ \`\`\`typescript
233
+ export const network = new ComputeNetwork({ autoCreateSubnetworks: false });
234
+
235
+ export const subnet = new ComputeSubnetwork({
236
+ networkRef: { name: network }, // Resolves to metadata.name of network
237
+ ipCidrRange: "10.0.0.0/24",
238
+ region: "us-central1",
239
+ });
240
+ \`\`\`
241
+
242
+ ## Project binding
243
+
244
+ Bind resources to a GCP project via annotations:
245
+
246
+ \`\`\`typescript
247
+ import { defaultAnnotations, GCP } from "@intentius/chant-lexicon-gcp";
248
+
249
+ export const annotations = defaultAnnotations({
250
+ "cnrm.cloud.google.com/project-id": GCP.ProjectId,
251
+ });
252
+ \`\`\`
253
+
254
+ This injects the project annotation into every resource. Without it, Config Connector uses the namespace's default project.
255
+
256
+ ## Reconciliation lifecycle
257
+
258
+ Config Connector resources go through a reconciliation lifecycle:
259
+
260
+ | Status | Meaning |
261
+ |--------|---------|
262
+ | UpToDate | Resource matches desired state |
263
+ | Updating | Controller is applying changes |
264
+ | UpdateFailed | GCP API returned an error |
265
+ | DependencyNotReady | Waiting for a referenced resource |
266
+ | DeletionFailed | Cannot delete the GCP resource |
267
+
268
+ Check status with: \`kubectl get gcp -A\` or \`kubectl describe <resource>\`
269
+
270
+ ## Default labels and annotations
271
+
272
+ Use \`defaultLabels()\` and \`defaultAnnotations()\` to inject metadata into all resources:
273
+
274
+ \`\`\`typescript
275
+ import { defaultLabels, defaultAnnotations } from "@intentius/chant-lexicon-gcp";
276
+
277
+ export const labels = defaultLabels({
278
+ "app.kubernetes.io/managed-by": "chant",
279
+ "env": "production",
280
+ });
281
+ \`\`\`
282
+
283
+ Explicit labels on individual resources take precedence over defaults.`,
284
+ },
285
+ {
286
+ slug: "lint-rules",
287
+ title: "Lint Rules",
288
+ description: "Built-in lint rules and post-synth checks for GCP Config Connector manifests",
289
+ content: `The GCP lexicon ships lint rules that run during \`chant lint\` and post-synth checks that validate the serialized YAML after \`chant build\`.
290
+
291
+ ## Lint rules
292
+
293
+ Lint rules analyze your TypeScript source code before build.
294
+
295
+ | Rule | Description |
296
+ |------|-------------|
297
+ | WGC001 | Hardcoded project ID in resource constructors |
298
+ | WGC002 | Hardcoded region in resource constructors |
299
+ | WGC003 | Public IAM member (allUsers/allAuthenticatedUsers) |
300
+
301
+ ## Post-synth checks
302
+
303
+ Post-synth checks run against the serialized YAML after build.
304
+
305
+ ### Security
306
+
307
+ | Rule | Description |
308
+ |------|-------------|
309
+ | WGC101 | Missing encryption on StorageBucket or SQLInstance |
310
+ | WGC102 | Public IAM member detected in output |
311
+ | WGC104 | Missing uniform bucket-level access |
312
+ | WGC105 | Cloud SQL with public 0.0.0.0/0 in authorizedNetworks |
313
+ | WGC109 | ComputeFirewall allowing all sources (0.0.0.0/0) |
314
+ | WGC110 | KMS CryptoKey without rotation period |
315
+
316
+ ### Best practices
317
+
318
+ | Rule | Description |
319
+ |------|-------------|
320
+ | WGC103 | Missing project annotation (uses namespace default) |
321
+ | WGC106 | Missing deletion policy annotation |
322
+ | WGC107 | StorageBucket without versioning |
323
+ | WGC108 | SQLInstance without backup configuration |
324
+ | WGC201 | Missing managed-by label |
325
+ | WGC202 | GKE cluster without workload identity |
326
+ | WGC203 | GKE node pool with overly broad cloud-platform OAuth scope |
327
+ | WGC204 | ComputeInstance without shielded VM config |
328
+
329
+ ### Compliance
330
+
331
+ | Rule | Description |
332
+ |------|-------------|
333
+ | WGC301 | No IAMAuditConfig resource in output |
334
+ | WGC302 | No Service (API enablement) resource in output |
335
+ | WGC303 | No VPC Service Controls perimeter |
336
+
337
+ ## Running lint
338
+
339
+ \`\`\`bash
340
+ # Lint your chant project
341
+ chant lint
342
+
343
+ # Build (also runs post-synth checks)
344
+ chant build
345
+ \`\`\`
346
+
347
+ To suppress a rule on a specific line:
348
+
349
+ \`\`\`typescript
350
+ // chant-disable-next-line WGC001
351
+ const bucket = new StorageBucket({ metadata: { annotations: { "cnrm.cloud.google.com/project-id": "my-project" } } });
352
+ \`\`\``,
353
+ },
354
+ {
355
+ slug: "examples",
356
+ title: "Examples: Resources",
357
+ description: "GCP Config Connector resource examples — StorageBucket, ComputeInstance, CloudSQL, IAM",
358
+ content: `## StorageBucket
359
+
360
+ A Storage bucket with encryption, versioning, and lifecycle rules:
361
+
362
+ \`\`\`typescript
363
+ import { StorageBucket, GCP } from "@intentius/chant-lexicon-gcp";
364
+
365
+ export const bucket = new StorageBucket({
366
+ location: "US",
367
+ storageClass: "STANDARD",
368
+ uniformBucketLevelAccess: true,
369
+ versioning: { enabled: true },
370
+ encryption: {
371
+ defaultKmsKeyName: "projects/p/locations/us/keyRings/kr/cryptoKeys/key",
372
+ },
373
+ lifecycleRule: [
374
+ { action: { type: "Delete" }, condition: { age: 365 } },
375
+ { action: { type: "SetStorageClass", storageClass: "NEARLINE" }, condition: { age: 30 } },
376
+ ],
377
+ });
378
+ \`\`\`
379
+
380
+ ## ComputeInstance
381
+
382
+ A Compute Engine VM with shielded VM configuration:
383
+
384
+ \`\`\`typescript
385
+ import { ComputeInstance, GCP } from "@intentius/chant-lexicon-gcp";
386
+
387
+ export const vm = new ComputeInstance({
388
+ machineType: "e2-medium",
389
+ zone: "us-central1-a",
390
+ bootDisk: {
391
+ initializeParams: {
392
+ sourceImageRef: {
393
+ external: "projects/debian-cloud/global/images/debian-12",
394
+ },
395
+ },
396
+ },
397
+ networkInterface: [{
398
+ networkRef: { name: "my-network" },
399
+ subnetworkRef: { name: "my-subnet" },
400
+ }],
401
+ shieldedInstanceConfig: {
402
+ enableSecureBoot: true,
403
+ enableVtpm: true,
404
+ enableIntegrityMonitoring: true,
405
+ },
406
+ });
407
+ \`\`\`
408
+
409
+ ## Cloud SQL
410
+
411
+ A PostgreSQL instance with backups and high availability:
412
+
413
+ \`\`\`typescript
414
+ import { CloudSqlInstance } from "@intentius/chant-lexicon-gcp";
415
+
416
+ const { instance, database, user } = CloudSqlInstance({
417
+ name: "app-db",
418
+ databaseVersion: "POSTGRES_15",
419
+ tier: "db-custom-2-8192",
420
+ region: "us-central1",
421
+ backupEnabled: true,
422
+ highAvailability: true,
423
+ diskSize: 50,
424
+ });
425
+
426
+ export { instance, database, user };
427
+ \`\`\`
428
+
429
+ ## IAM Binding
430
+
431
+ Grant a service account access to a resource:
432
+
433
+ \`\`\`typescript
434
+ import { IAMPolicyMember } from "@intentius/chant-lexicon-gcp";
435
+
436
+ export const binding = new IAMPolicyMember({
437
+ member: "serviceAccount:app@my-project.iam.gserviceaccount.com",
438
+ role: "roles/storage.objectViewer",
439
+ resourceRef: {
440
+ apiVersion: "storage.cnrm.cloud.google.com/v1beta1",
441
+ kind: "StorageBucket",
442
+ name: "my-bucket",
443
+ },
444
+ });
445
+ \`\`\``,
446
+ },
447
+ {
448
+ slug: "composite-examples",
449
+ title: "Examples: Composites",
450
+ description: "All 10 GCP composites with full code and deployment workflow",
451
+ content: `Composites are higher-level constructs that produce multiple coordinated Config Connector resources from a single function call.
452
+
453
+ ## GkeCluster
454
+
455
+ GKE cluster with node pool and workload identity:
456
+
457
+ \`\`\`typescript
458
+ import { GkeCluster } from "@intentius/chant-lexicon-gcp";
459
+
460
+ const { cluster, nodePool } = GkeCluster({
461
+ name: "my-cluster",
462
+ location: "us-central1",
463
+ machineType: "e2-standard-4",
464
+ minNodeCount: 1,
465
+ maxNodeCount: 10,
466
+ workloadIdentity: true,
467
+ });
468
+
469
+ export { cluster, nodePool };
470
+ \`\`\`
471
+
472
+ ## CloudRunService
473
+
474
+ Cloud Run service with optional public access:
475
+
476
+ \`\`\`typescript
477
+ import { CloudRunService } from "@intentius/chant-lexicon-gcp";
478
+
479
+ const { service, publicIam } = CloudRunService({
480
+ name: "my-api",
481
+ image: "gcr.io/my-project/api:1.0",
482
+ port: 8080,
483
+ publicAccess: true,
484
+ minInstanceCount: 1,
485
+ maxInstanceCount: 10,
486
+ });
487
+
488
+ export { service, publicIam };
489
+ \`\`\`
490
+
491
+ ## CloudSqlInstance
492
+
493
+ PostgreSQL with database and user:
494
+
495
+ \`\`\`typescript
496
+ import { CloudSqlInstance } from "@intentius/chant-lexicon-gcp";
497
+
498
+ const { instance, database, user } = CloudSqlInstance({
499
+ name: "app-db",
500
+ tier: "db-custom-2-8192",
501
+ backupEnabled: true,
502
+ highAvailability: true,
503
+ });
504
+
505
+ export { instance, database, user };
506
+ \`\`\`
507
+
508
+ ## GcsBucket
509
+
510
+ Storage bucket with encryption and lifecycle:
511
+
512
+ \`\`\`typescript
513
+ import { GcsBucket } from "@intentius/chant-lexicon-gcp";
514
+
515
+ const { bucket } = GcsBucket({
516
+ name: "data-lake",
517
+ location: "US",
518
+ versioning: true,
519
+ kmsKeyName: "projects/p/locations/us/keyRings/kr/cryptoKeys/key",
520
+ lifecycleDeleteAfterDays: 365,
521
+ lifecycleNearlineAfterDays: 30,
522
+ });
523
+
524
+ export { bucket };
525
+ \`\`\`
526
+
527
+ ## VpcNetwork
528
+
529
+ VPC with subnets, firewalls, and Cloud NAT:
530
+
531
+ \`\`\`typescript
532
+ import { VpcNetwork } from "@intentius/chant-lexicon-gcp";
533
+
534
+ const { network, subnets, firewalls, router, routerNat } = VpcNetwork({
535
+ name: "production",
536
+ subnets: [
537
+ { name: "app", ipCidrRange: "10.0.0.0/24", region: "us-central1" },
538
+ { name: "data", ipCidrRange: "10.0.1.0/24", region: "us-central1" },
539
+ ],
540
+ enableNat: true,
541
+ natRegion: "us-central1",
542
+ allowIapSsh: true,
543
+ });
544
+
545
+ export { network, subnets, firewalls, router, routerNat };
546
+ \`\`\`
547
+
548
+ ## PubSubPipeline
549
+
550
+ Topic + Subscription + optional dead-letter queue:
551
+
552
+ \`\`\`typescript
553
+ import { PubSubPipeline } from "@intentius/chant-lexicon-gcp";
554
+
555
+ const { topic, subscription, deadLetterTopic, subscriberIam } = PubSubPipeline({
556
+ name: "order-events",
557
+ enableDeadLetterQueue: true,
558
+ maxDeliveryAttempts: 5,
559
+ subscriberServiceAccount: "worker@my-project.iam.gserviceaccount.com",
560
+ });
561
+
562
+ export { topic, subscription, deadLetterTopic, subscriberIam };
563
+ \`\`\`
564
+
565
+ ## CloudFunctionWithTrigger
566
+
567
+ Cloud Function + source bucket + optional public invoker IAM:
568
+
569
+ \`\`\`typescript
570
+ import { CloudFunctionWithTrigger } from "@intentius/chant-lexicon-gcp";
571
+
572
+ const { function: fn, sourceBucket, invokerIam } = CloudFunctionWithTrigger({
573
+ name: "process-upload",
574
+ runtime: "nodejs20",
575
+ entryPoint: "handler",
576
+ triggerType: "pubsub",
577
+ triggerTopic: "file-uploads",
578
+ region: "us-central1",
579
+ });
580
+
581
+ export { fn, sourceBucket, invokerIam };
582
+ \`\`\`
583
+
584
+ ## PrivateService
585
+
586
+ Private service networking (VPC peering):
587
+
588
+ \`\`\`typescript
589
+ import { PrivateService } from "@intentius/chant-lexicon-gcp";
590
+
591
+ const { globalAddress, serviceConnection, dnsZone } = PrivateService({
592
+ name: "db-peering",
593
+ networkName: "production",
594
+ enableDns: true,
595
+ });
596
+
597
+ export { globalAddress, serviceConnection, dnsZone };
598
+ \`\`\`
599
+
600
+ ## ManagedCertificate
601
+
602
+ Google-managed SSL certificate + optional HTTPS proxy:
603
+
604
+ \`\`\`typescript
605
+ import { ManagedCertificate } from "@intentius/chant-lexicon-gcp";
606
+
607
+ const { certificate, targetHttpsProxy, urlMap } = ManagedCertificate({
608
+ name: "web-cert",
609
+ domains: ["example.com", "www.example.com"],
610
+ createProxy: true,
611
+ backendServiceName: "web-backend",
612
+ });
613
+
614
+ export { certificate, targetHttpsProxy, urlMap };
615
+ \`\`\`
616
+
617
+ ## SecureProject
618
+
619
+ Project with audit logging, API enablement, and IAM:
620
+
621
+ \`\`\`typescript
622
+ import { SecureProject } from "@intentius/chant-lexicon-gcp";
623
+
624
+ const { project, auditConfig, services, ownerIam, loggingSink } = SecureProject({
625
+ name: "my-project",
626
+ orgId: "123456789",
627
+ billingAccountRef: "ABCDEF-123456-ABCDEF",
628
+ owner: "user:admin@example.com",
629
+ loggingSinkDestination: "bigquery.googleapis.com/projects/audit/datasets/logs",
630
+ });
631
+
632
+ export { project, auditConfig, services, ownerIam, loggingSink };
633
+ \`\`\`
634
+
635
+ ## Deploying composites
636
+
637
+ \`\`\`bash
638
+ # Build YAML manifests
639
+ chant build src/ --output manifests.yaml
640
+
641
+ # Lint for common issues
642
+ chant lint src/
643
+
644
+ # Dry run
645
+ kubectl apply -f manifests.yaml --dry-run=server
646
+
647
+ # Apply
648
+ kubectl apply -f manifests.yaml
649
+ \`\`\``,
650
+ },
651
+ {
652
+ slug: "operational-playbook",
653
+ title: "Operational Playbook",
654
+ description: "Build, lint, apply, troubleshoot Config Connector resources",
655
+ content: `This playbook covers the full lifecycle of chant-produced Config Connector manifests.
656
+
657
+ ## Build & validate
658
+
659
+ | Step | Command | What it catches |
660
+ |------|---------|-----------------|
661
+ | Lint source | \`chant lint src/\` | Hardcoded project IDs (WGC001), regions (WGC002), public IAM (WGC003) |
662
+ | Build manifests | \`chant build src/ --output manifests.yaml\` | Post-synth: missing encryption (WGC101), public IAM (WGC102), missing project annotation (WGC103), 14 more checks |
663
+ | Server dry-run | \`kubectl apply -f manifests.yaml --dry-run=server\` | K8s API validation: CRD schema errors, admission webhooks |
664
+
665
+ ## Deploy to Kubernetes
666
+
667
+ \`\`\`bash
668
+ # Build
669
+ chant build src/ --output manifests.yaml
670
+
671
+ # Diff before applying
672
+ kubectl diff -f manifests.yaml
673
+
674
+ # Dry run
675
+ kubectl apply -f manifests.yaml --dry-run=server
676
+
677
+ # Apply
678
+ kubectl apply -f manifests.yaml
679
+ \`\`\`
680
+
681
+ ## Monitoring reconciliation
682
+
683
+ \`\`\`bash
684
+ # List all Config Connector resources
685
+ kubectl get gcp -A
686
+
687
+ # Check specific resource status
688
+ kubectl describe storagebuckets.storage.cnrm.cloud.google.com my-bucket
689
+
690
+ # Watch for status changes
691
+ kubectl get gcp -A -w
692
+ \`\`\`
693
+
694
+ ## Troubleshooting
695
+
696
+ | Status | Meaning | Diagnostic | Fix |
697
+ |--------|---------|------------|-----|
698
+ | UpToDate | Resource in sync | None needed | — |
699
+ | Updating | Applying changes | \`kubectl describe\` → Events | Wait for completion |
700
+ | UpdateFailed | GCP API error | \`kubectl describe\` → Events | Check IAM permissions, quota, API enablement |
701
+ | DependencyNotReady | Waiting for ref | \`kubectl get gcp\` | Ensure referenced resource exists and is UpToDate |
702
+ | DeletionFailed | Cannot delete | \`kubectl describe\` → Events | Check IAM permissions, child resource dependencies |
703
+
704
+ ## Common issues
705
+
706
+ | Symptom | Cause | Resolution |
707
+ |---------|-------|------------|
708
+ | Resource stuck in Updating | Missing GCP API | Enable API: add Service resource or \`gcloud services enable\` |
709
+ | Permission denied | Service account lacks IAM role | Grant role to Config Connector SA |
710
+ | Resource recreated on every apply | Missing deletion-policy annotation | Add \`cnrm.cloud.google.com/deletion-policy: abandon\` |
711
+ | Namespace not found | ConfigConnectorContext missing | Create ConfigConnectorContext in namespace |
712
+ | Cross-project reference fails | Missing project annotation | Add \`cnrm.cloud.google.com/project-id\` annotation |
713
+
714
+ ## Quick reference
715
+
716
+ | Command | Description |
717
+ |---------|-------------|
718
+ | \`chant build src/\` | Synthesize manifests |
719
+ | \`chant lint src/\` | Check for anti-patterns |
720
+ | \`kubectl apply -f manifests.yaml\` | Apply to cluster |
721
+ | \`kubectl get gcp -A\` | List all Config Connector resources |
722
+ | \`kubectl describe <resource>\` | Check reconciliation status |
723
+ | \`kubectl delete -f manifests.yaml\` | Remove resources |`,
724
+ },
725
+ {
726
+ slug: "importing-yaml",
727
+ title: "Importing Existing YAML",
728
+ description: "Convert existing Config Connector YAML into typed TypeScript",
729
+ content: `Chant can parse existing Config Connector YAML manifests and generate typed TypeScript source files.
730
+
731
+ ## How it works
732
+
733
+ \`\`\`
734
+ Input YAML → parse → generate TypeScript → export typed resources
735
+ \`\`\`
736
+
737
+ The importer reads multi-document YAML, identifies Config Connector resources by their \`cnrm.cloud.google.com\` apiVersion, and generates corresponding typed constructor calls.
738
+
739
+ ## Example
740
+
741
+ Input YAML:
742
+
743
+ \`\`\`yaml
744
+ apiVersion: storage.cnrm.cloud.google.com/v1beta1
745
+ kind: StorageBucket
746
+ metadata:
747
+ name: my-bucket
748
+ spec:
749
+ location: US
750
+ uniformBucketLevelAccess: true
751
+ \`\`\`
752
+
753
+ Generated TypeScript:
754
+
755
+ \`\`\`typescript
756
+ import { Bucket } from "@intentius/chant-lexicon-gcp";
757
+
758
+ export const myBucket = new Bucket({
759
+ metadata: { name: "my-bucket" },
760
+ location: "US",
761
+ uniformBucketLevelAccess: true,
762
+ });
763
+ \`\`\`
764
+
765
+ ## Limitations
766
+
767
+ The import pipeline:
768
+
769
+ - Only handles Config Connector resources (\`cnrm.cloud.google.com\` apiVersion)
770
+ - Non-CC resources (standard K8s Deployments, Services) are filtered out
771
+ - Resource references are preserved as literal values, not typed refs
772
+ - Multi-document YAML is fully supported`,
773
+ },
774
+ {
775
+ slug: "skills",
776
+ title: "AI Skills",
777
+ description: "AI agent skills bundled with the GCP lexicon",
778
+ content: `The GCP lexicon ships an AI skill called **chant-gcp** that teaches AI coding agents how to build, validate, and deploy Config Connector manifests from a chant project.
779
+
780
+ ## What are skills?
781
+
782
+ Skills are structured markdown documents bundled with a lexicon. When an AI agent works in a chant project, it discovers and loads relevant skills automatically.
783
+
784
+ ## Installation
785
+
786
+ When you scaffold a new project with \`chant init --lexicon gcp\`, the skill is installed to \`skills/chant-gcp/SKILL.md\`.
787
+
788
+ ## Skill: chant-gcp
789
+
790
+ The \`chant-gcp\` skill covers:
791
+
792
+ - **Build** — \`chant build src/ --output manifests.yaml\`
793
+ - **Lint** — \`chant lint src/\` + 17 post-synth checks
794
+ - **Apply** — \`kubectl apply -f manifests.yaml\`
795
+ - **Status** — \`kubectl get gcp -A\`
796
+ - **Troubleshooting** — reconciliation status, events, common error patterns
797
+
798
+ ## MCP integration
799
+
800
+ | MCP tool | Description |
801
+ |----------|-------------|
802
+ | \`diff\` | Compare current build output against previous |
803
+
804
+ | MCP resource | Description |
805
+ |--------------|-------------|
806
+ | \`resource-catalog\` | JSON list of all supported Config Connector resource types |
807
+ | \`examples/basic-bucket\` | Example StorageBucket code |`,
808
+ },
809
+ ],
810
+ };
811
+
812
+ const result = docsPipeline(config);
813
+ writeDocsSite(config, result);
814
+
815
+ if (opts?.verbose) {
816
+ console.error(
817
+ `Generated docs: ${result.stats.resources} resources, ${result.stats.properties} properties, ${result.stats.services} services, ${result.stats.rules} rules`,
818
+ );
819
+ }
820
+ }