[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6NTWBP1F7YF9E8AXHD4BCNF":3,"skill-same:01M6NTWBP1F7YF9E8AXHD4BCNF":58},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":31,"linkOnly":32,"markdownContent":33,"markdownBody":34,"frontMatter":35,"refName":36,"commitSha":37,"skillDirectory":38,"forksCount":14,"repositoryHtmlUrl":39,"repositoryHomepageUrl":6,"ownerHtmlUrl":40,"ownerBlogUrl":41,"ownerDescription":42,"updatedAt":43,"install":44,"resources":57},"01M6NTWBP1F7YF9E8AXHD4BCNF","gcp-patterns",null,"Cloud Run deployment, BigQuery optimization, Pub\u002FSub patterns, IAM best practices","rubicanjr\u002FFinCognis","rubicanjr","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F234912519?v=4","01M6NT156NND8J474G34SB3923","Rubi","01M6NT15B70RWXE1N3YV0BZY8A",0,"MIT","https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis\u002Fblob\u002Fmain\u002Fskills\u002Fgcp-patterns\u002Fskill.md",[],[19,20,21,22,23,24,25,26,27,28,29,30],"gcp","patterns","gcp patterns","bigquery optimization","deployment","run","best practices","bigquery","cloud","Optimization","iam","cloud run","2026-11-10 10:12:30",false,"---\nname: gcp-patterns\ndescription: Cloud Run deployment, BigQuery optimization, Pub\u002FSub patterns, IAM best practices\n---\n\n# GCP Patterns\n\n## Cloud Run Deployment\n\n### Dockerfile for Cloud Run\n\n```dockerfile\nFROM node:20-slim AS builder\nWORKDIR \u002Fapp\nCOPY package*.json .\u002F\nRUN npm ci --production=false\nCOPY . .\nRUN npm run build\n\nFROM node:20-slim\nWORKDIR \u002Fapp\nRUN addgroup --system app && adduser --system --ingroup app app\nCOPY --from=builder \u002Fapp\u002Fdist .\u002Fdist\nCOPY --from=builder \u002Fapp\u002Fnode_modules .\u002Fnode_modules\nCOPY --from=builder \u002Fapp\u002Fpackage.json .\u002F\nUSER app\nEXPOSE 8080\nENV PORT=8080 NODE_ENV=production\nCMD [\"node\", \"dist\u002Fserver.js\"]\n```\n\n### Cloud Run Service YAML\n\n```yaml\napiVersion: serving.knative.dev\u002Fv1\nkind: Service\nmetadata:\n  name: order-service\n  annotations:\n    run.googleapis.com\u002Flaunch-stage: GA\nspec:\n  template:\n    metadata:\n      annotations:\n        autoscaling.knative.dev\u002FminScale: \"1\"\n        autoscaling.knative.dev\u002FmaxScale: \"100\"\n        run.googleapis.com\u002Fcpu-throttling: \"false\"\n        run.googleapis.com\u002Fstartup-cpu-boost: \"true\"\n    spec:\n      containerConcurrency: 80\n      timeoutSeconds: 300\n      serviceAccountName: order-service@project-id.iam.gserviceaccount.com\n      containers:\n        - image: gcr.io\u002Fproject-id\u002Forder-service:latest\n          ports:\n            - containerPort: 8080\n          resources:\n            limits:\n              cpu: \"2\"\n              memory: 1Gi\n          env:\n            - name: DB_CONNECTION\n              valueFrom:\n                secretKeyRef:\n                  key: latest\n                  name: db-connection-string\n          startupProbe:\n            httpGet:\n              path: \u002Fhealthz\n              port: 8080\n            initialDelaySeconds: 5\n            periodSeconds: 3\n```\n\n### Deploy Command\n\n```bash\ngcloud run deploy order-service \\\n  --image gcr.io\u002F$PROJECT_ID\u002Forder-service:$GIT_SHA \\\n  --region us-central1 \\\n  --service-account order-service@$PROJECT_ID.iam.gserviceaccount.com \\\n  --set-secrets \"DB_URL=db-connection:latest\" \\\n  --min-instances 1 \\\n  --max-instances 100 \\\n  --cpu 2 --memory 1Gi \\\n  --concurrency 80 \\\n  --no-allow-unauthenticated\n```\n\n## BigQuery Optimization\n\n```sql\n-- Use partitioning and clustering\nCREATE TABLE `project.dataset.events`\nPARTITION BY DATE(event_timestamp)\nCLUSTER BY user_id, event_type\nAS SELECT * FROM `project.dataset.raw_events`;\n\n-- Always filter on partition column\nSELECT event_type, COUNT(*) as cnt\nFROM `project.dataset.events`\nWHERE event_timestamp BETWEEN '2025-01-01' AND '2025-01-31'\n  AND event_type = 'purchase'\nGROUP BY event_type;\n\n-- Use approximate functions for large datasets\nSELECT APPROX_COUNT_DISTINCT(user_id) as unique_users\nFROM `project.dataset.events`\nWHERE DATE(event_timestamp) = CURRENT_DATE();\n\n-- Avoid SELECT * (scans all columns, costs more)\n-- Use column selection and LIMIT for exploration\n```\n\n## Pub\u002FSub Patterns\n\n```python\nfrom google.cloud import pubsub_v1\nfrom google.api_core import retry\nimport json\n\n# Publisher with ordering and retry\npublisher = pubsub_v1.PublisherClient()\ntopic_path = publisher.topic_path(\"project-id\", \"order-events\")\n\ndef publish_event(event: dict, ordering_key: str = \"\") -> str:\n    data = json.dumps(event).encode(\"utf-8\")\n    future = publisher.publish(\n        topic_path,\n        data,\n        ordering_key=ordering_key,\n        event_type=event[\"type\"],\n    )\n    return future.result(timeout=30)\n\n# Subscriber with exactly-once processing\nsubscriber = pubsub_v1.SubscriberClient()\nsubscription_path = subscriber.subscription_path(\"project-id\", \"order-events-sub\")\n\ndef callback(message: pubsub_v1.types.PubsubMessage) -> None:\n    try:\n        event = json.loads(message.data.decode(\"utf-8\"))\n        idempotency_key = message.message_id\n\n        if already_processed(idempotency_key):\n            message.ack()\n            return\n\n        process_event(event)\n        mark_processed(idempotency_key)\n        message.ack()\n    except Exception as e:\n        logger.error(f\"Failed to process message: {e}\")\n        message.nack()\n\nsubscriber.subscribe(subscription_path, callback=callback)\n```\n\n## IAM Best Practices\n\n```yaml\nPrinciples:\n  - Least privilege: grant minimum permissions needed\n  - Service accounts per service (not shared)\n  - No user accounts in production workloads\n  - Prefer predefined roles over primitive roles\n\nPer-Service Pattern:\n  order-service:\n    roles:\n      - roles\u002Fcloudsql.client          # DB access\n      - roles\u002Fpubsub.publisher         # Publish events\n      - roles\u002Fsecretmanager.secretAccessor  # Read secrets\n    # NOT: roles\u002Feditor (too broad)\n\nWorkload Identity (GKE):\n  - Bind K8s SA to GCP SA\n  - No key files, automatic credential rotation\n```\n\n## Checklist\n\n- [ ] Cloud Run services use dedicated service accounts\n- [ ] Secrets stored in Secret Manager, not env vars\n- [ ] BigQuery tables partitioned and clustered\n- [ ] Pub\u002FSub subscribers implement idempotent processing\n- [ ] Health check endpoints configured for all services\n- [ ] Min instances set for latency-sensitive services\n- [ ] IAM follows least privilege (no primitive roles)\n- [ ] Cloud Armor WAF in front of public endpoints\n- [ ] VPC connector for private resource access\n\n## Anti-Patterns\n\n- Using default compute service account (overprivileged)\n- SELECT * on BigQuery (scans all columns, high cost)\n- Pub\u002FSub without dead letter queue (messages lost on repeated failure)\n- Hardcoding project ID instead of using environment detection\n- Not setting concurrency limits on Cloud Run (OOM under load)\n- Using Cloud Run for long-running background jobs (use Cloud Tasks)\n- Storing secrets in environment variables instead of Secret Manager\n","# GCP Patterns\n\n## Cloud Run Deployment\n\n### Dockerfile for Cloud Run\n\n```dockerfile\nFROM node:20-slim AS builder\nWORKDIR \u002Fapp\nCOPY package*.json .\u002F\nRUN npm ci --production=false\nCOPY . .\nRUN npm run build\n\nFROM node:20-slim\nWORKDIR \u002Fapp\nRUN addgroup --system app && adduser --system --ingroup app app\nCOPY --from=builder \u002Fapp\u002Fdist .\u002Fdist\nCOPY --from=builder \u002Fapp\u002Fnode_modules .\u002Fnode_modules\nCOPY --from=builder \u002Fapp\u002Fpackage.json .\u002F\nUSER app\nEXPOSE 8080\nENV PORT=8080 NODE_ENV=production\nCMD [\"node\", \"dist\u002Fserver.js\"]\n```\n\n### Cloud Run Service YAML\n\n```yaml\napiVersion: serving.knative.dev\u002Fv1\nkind: Service\nmetadata:\n  name: order-service\n  annotations:\n    run.googleapis.com\u002Flaunch-stage: GA\nspec:\n  template:\n    metadata:\n      annotations:\n        autoscaling.knative.dev\u002FminScale: \"1\"\n        autoscaling.knative.dev\u002FmaxScale: \"100\"\n        run.googleapis.com\u002Fcpu-throttling: \"false\"\n        run.googleapis.com\u002Fstartup-cpu-boost: \"true\"\n    spec:\n      containerConcurrency: 80\n      timeoutSeconds: 300\n      serviceAccountName: order-service@project-id.iam.gserviceaccount.com\n      containers:\n        - image: gcr.io\u002Fproject-id\u002Forder-service:latest\n          ports:\n            - containerPort: 8080\n          resources:\n            limits:\n              cpu: \"2\"\n              memory: 1Gi\n          env:\n            - name: DB_CONNECTION\n              valueFrom:\n                secretKeyRef:\n                  key: latest\n                  name: db-connection-string\n          startupProbe:\n            httpGet:\n              path: \u002Fhealthz\n              port: 8080\n            initialDelaySeconds: 5\n            periodSeconds: 3\n```\n\n### Deploy Command\n\n```bash\ngcloud run deploy order-service \\\n  --image gcr.io\u002F$PROJECT_ID\u002Forder-service:$GIT_SHA \\\n  --region us-central1 \\\n  --service-account order-service@$PROJECT_ID.iam.gserviceaccount.com \\\n  --set-secrets \"DB_URL=db-connection:latest\" \\\n  --min-instances 1 \\\n  --max-instances 100 \\\n  --cpu 2 --memory 1Gi \\\n  --concurrency 80 \\\n  --no-allow-unauthenticated\n```\n\n## BigQuery Optimization\n\n```sql\n-- Use partitioning and clustering\nCREATE TABLE `project.dataset.events`\nPARTITION BY DATE(event_timestamp)\nCLUSTER BY user_id, event_type\nAS SELECT * FROM `project.dataset.raw_events`;\n\n-- Always filter on partition column\nSELECT event_type, COUNT(*) as cnt\nFROM `project.dataset.events`\nWHERE event_timestamp BETWEEN '2025-01-01' AND '2025-01-31'\n  AND event_type = 'purchase'\nGROUP BY event_type;\n\n-- Use approximate functions for large datasets\nSELECT APPROX_COUNT_DISTINCT(user_id) as unique_users\nFROM `project.dataset.events`\nWHERE DATE(event_timestamp) = CURRENT_DATE();\n\n-- Avoid SELECT * (scans all columns, costs more)\n-- Use column selection and LIMIT for exploration\n```\n\n## Pub\u002FSub Patterns\n\n```python\nfrom google.cloud import pubsub_v1\nfrom google.api_core import retry\nimport json\n\n# Publisher with ordering and retry\npublisher = pubsub_v1.PublisherClient()\ntopic_path = publisher.topic_path(\"project-id\", \"order-events\")\n\ndef publish_event(event: dict, ordering_key: str = \"\") -> str:\n    data = json.dumps(event).encode(\"utf-8\")\n    future = publisher.publish(\n        topic_path,\n        data,\n        ordering_key=ordering_key,\n        event_type=event[\"type\"],\n    )\n    return future.result(timeout=30)\n\n# Subscriber with exactly-once processing\nsubscriber = pubsub_v1.SubscriberClient()\nsubscription_path = subscriber.subscription_path(\"project-id\", \"order-events-sub\")\n\ndef callback(message: pubsub_v1.types.PubsubMessage) -> None:\n    try:\n        event = json.loads(message.data.decode(\"utf-8\"))\n        idempotency_key = message.message_id\n\n        if already_processed(idempotency_key):\n            message.ack()\n            return\n\n        process_event(event)\n        mark_processed(idempotency_key)\n        message.ack()\n    except Exception as e:\n        logger.error(f\"Failed to process message: {e}\")\n        message.nack()\n\nsubscriber.subscribe(subscription_path, callback=callback)\n```\n\n## IAM Best Practices\n\n```yaml\nPrinciples:\n  - Least privilege: grant minimum permissions needed\n  - Service accounts per service (not shared)\n  - No user accounts in production workloads\n  - Prefer predefined roles over primitive roles\n\nPer-Service Pattern:\n  order-service:\n    roles:\n      - roles\u002Fcloudsql.client          # DB access\n      - roles\u002Fpubsub.publisher         # Publish events\n      - roles\u002Fsecretmanager.secretAccessor  # Read secrets\n    # NOT: roles\u002Feditor (too broad)\n\nWorkload Identity (GKE):\n  - Bind K8s SA to GCP SA\n  - No key files, automatic credential rotation\n```\n\n## Checklist\n\n- [ ] Cloud Run services use dedicated service accounts\n- [ ] Secrets stored in Secret Manager, not env vars\n- [ ] BigQuery tables partitioned and clustered\n- [ ] Pub\u002FSub subscribers implement idempotent processing\n- [ ] Health check endpoints configured for all services\n- [ ] Min instances set for latency-sensitive services\n- [ ] IAM follows least privilege (no primitive roles)\n- [ ] Cloud Armor WAF in front of public endpoints\n- [ ] VPC connector for private resource access\n\n## Anti-Patterns\n\n- Using default compute service account (overprivileged)\n- SELECT * on BigQuery (scans all columns, high cost)\n- Pub\u002FSub without dead letter queue (messages lost on repeated failure)\n- Hardcoding project ID instead of using environment detection\n- Not setting concurrency limits on Cloud Run (OOM under load)\n- Using Cloud Run for long-running background jobs (use Cloud Tasks)\n- Storing secrets in environment variables instead of Secret Manager\n",{"name":5,"description":7},"main","70e1c350500ee750987420bbae48837afa906b7e","skills\u002Fgcp-patterns","https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis","https:\u002F\u002Fgithub.com\u002Frubicanjr","linktr.ee\u002Ffinanskodu","Industrial Engineer & CIO @FinansKodu. Architecting AI-driven financial agents and autonomous workflows. 🏗️ Building systems, not just prompts.","2026-06-09 13:50:15",{"source":8,"skillName":5,"commands":45,"prompt":55,"zipAvailable":56},[46,49,52],{"tool":47,"command":48},"npx","npx skills add rubicanjr\u002FFinCognis --skill gcp-patterns",{"tool":50,"command":51},"bunx","bunx skills add rubicanjr\u002FFinCognis --skill gcp-patterns",{"tool":53,"command":54},"pnpm","pnpm dlx skills add rubicanjr\u002FFinCognis --skill gcp-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis\u002Fblob\u002Fmain\u002Fskills\u002Fgcp-patterns\u002Fskill.md",true,[],[59,80,89,108,138,157],{"skillNo":60,"name":61,"nameZh":6,"description":62,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":70,"publishedAt":31},"01M6NWS9DAXJTADT4T5MB49X8W","workflow-router","Goal-based workflow orchestration - routes tasks to specialist agents based on user goals","https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis\u002Fblob\u002Fmain\u002Fskills\u002Fworkflow-router\u002FSKILL.md",[65],{"categoryNo":66,"categoryName":67,"taxonomyType":68,"taxonomyTypeDesc":69},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[71,72,73,74,75,76,77,78,79],"workflow router","workflow","router","orchestration","goals","goal","user","workflow orchestration","tasks",{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":31},"01M6NWS3RETSC0SHP16HP66E14","wiring","Wiring Verification","https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis\u002Fblob\u002Fmain\u002Fskills\u002Fwiring\u002FSKILL.md",[],[82,87,88],"verification","false",{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":93,"categories":94,"keywords":98,"publishedAt":31},"01M6NWS0XW9CVQZBDA1EGW0TWC","websocket-patterns","Connection management, room patterns, reconnection strategies, message buffering, and binary protocol design.","https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis\u002Fblob\u002Fmain\u002Fskills\u002Fwebsocket-patterns\u002Fskill.md",[95],{"categoryNo":96,"categoryName":97,"taxonomyType":68,"taxonomyTypeDesc":69},"01JBSEEDCAT000000000000015","视觉设计",[99,20,100,101,102,103,104,105,106,107],"websocket","websocket patterns","design","protocol","management","message","strategies","binary","connection",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":118,"publishedAt":31},"01M6NWRDQDX9ZNETAWRRMQWV52","visual-verdict","Screenshot comparison QA for frontend development. Takes a screenshot of the current implementation, scores it across multiple visual dimensions, and returns a structured PASS\u002FREVISE\u002FFAIL verdict with concrete fixes. Use when implementing UI from a design reference or verifying visual correctness.","https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis\u002Fblob\u002Fmain\u002Fskills\u002Fvisual-verdict\u002FSKILL.md",[114,117],{"categoryNo":115,"categoryName":116,"taxonomyType":68,"taxonomyTypeDesc":69},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":66,"categoryName":67,"taxonomyType":68,"taxonomyTypeDesc":69},[119,120,121,122,123,124,125,126,127,128,129,130,131,101,132,133,134,135,136,137],"visual","verdict","visual verdict","ui","across","revise","comparison","correctness","implementing","for","fixes","dimensions","frontend","development","qa","screenshot","returns","use","frontend development",{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":144,"publishedAt":31},"01M6NWR8HSNRS7MNDK2J02QYMN","verification-loop","Comprehensive verification system covering build, types, lint, tests, security, and diff review before a PR.","https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis\u002Fblob\u002Fmain\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[145,146,87,147,148,149,150,151,152,153,154,155,156],"verification loop","loop","lint","review","security","pr","system","diff","build","tests","diff review","types",{"skillNo":158,"name":159,"nameZh":6,"description":160,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":161,"categories":162,"keywords":163,"publishedAt":31},"01M6NWR4HHSFR0VR5EXFRWA747","vector-db-patterns","Embedding strategies, ANN algorithms, hybrid search, RAG chunking strategies, and reranking for semantic search and retrieval.","https:\u002F\u002Fgithub.com\u002Frubicanjr\u002FFinCognis\u002Fblob\u002Fmain\u002Fskills\u002Fvector-db-patterns\u002Fskill.md",[],[164,165,166,167,20,168,169,170,171,105,172,173,174,175,176,128,177,178],"vector db patterns","vector db","db","vector","semantic search","search","embedding strategies","algorithms","chunking","semantic","retrieval","embedding","Hybrid Search","hybrid","rag"]