Skip to content

Commit a2ec882

Browse files
chore: sync from CloudBase-MCP
1 parent 9cfd3b1 commit a2ec882

4 files changed

Lines changed: 33 additions & 30 deletions

File tree

‎generated/skill-manifest.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"version": 2,
3-
"generatedAt": "2026-10-15T10:51:08.539Z",
3+
"generatedAt": "2026-10-16T02:58:09.598Z",
44
"skills": {
55
"ai-model-nodejs": {
66
"name": "ai-model-nodejs",

‎skills/cloud-functions/SKILL.md‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ If a referenced sibling skill file is missing from this environment, ask the use
6666
- Using cloud functions as the first answer for Web login.
6767
- Forgetting that HTTP Functions must ship `scf_bootstrap`, listen on port `9000`, and include dependencies.
6868
- Assuming an HTTP Function can use CloudBase SDKs without explicit credentials. The default temporary credential path is not reliable for HTTP Functions and credential rotation can break a running service. Use a CloudBase server API Key or Tencent Cloud key pair for `@cloudbase/node-sdk`; use a Tencent Cloud key pair for `@cloudbase/manager-node`. See `references/http-function-credentials.md`.
69-
- Forgetting to configure function security rules after creating an HTTP Function. Default rules reject anonymous callers with `EXCEED_AUTHORITY`. Note: anonymous login is disabled by default for new environments — if the function needs public access without authentication, configure the security rule to allow all callers rather than relying on anonymous login.
69+
- Forgetting how an HTTP Function is meant to be reached. A call with no credential fails `401 MISSING_CREDENTIALS`; a call that carries one but is not allowed fails `403 EXCEED_AUTHORITY`. For browser, game or app clients, add a gateway route (`manageGateway(action="createRoute", auth: false)`) instead of widening the function security rule — in PostgreSQL environments that rule lives in an environment-wide `authz.user.rego` document, so editing it overwrites the policy for the whole environment. See `references/http-functions.md`.
7070
- **Reading an `InsufficientBalance` invoke failure as an account problem.** A cloud function answers HTTP 410 with this code and the code reads as a short account balance, but what runs out is the environment's resource points — drawn down before any account balance and not restored by a top-up. The four causes (trial points exhausted / plan points exhausted / plan expired / account in arrears) need four different answers, only the last of which involves topping up, so diagnose with `manageEnv(action="usage")` plus the account balance before advising. See `../cloud-api-operations/references/recipes/credits-exhaustion.md`.
7171
- Mismatching the `scf_bootstrap` Node.js binary path with the function runtime (e.g. using `/var/lang/node18/bin/node` but setting `runtime: "Nodejs16.13"`).
7272
- For Custom Image HTTP Functions: forgetting that TCR, the CloudApp build, and SCF must be in the same region; using `:latest` instead of a unique tag; or confusing the request-driven port-`9000` image model with a long-lived CloudRun container that listens on the injected `PORT`.
@@ -147,9 +147,9 @@ Use these rules whenever you are writing the function code itself:
147147
- If you do choose ES Modules (`"type": "module"` + `import ...`), do not mix in CommonJS-only globals or APIs such as `require(...)`, `module.exports`, or bare `__dirname`. In ESM, derive file paths from `import.meta.url` with `fileURLToPath(...)` only when needed.
148148
- With the native `http` module, parse `req.url` yourself with `new URL(...)`, collect the request body from the stream, and only then call `JSON.parse`. Empty bodies should be handled explicitly instead of assuming JSON is always present.
149149
- Return responses explicitly with `res.writeHead(...)` and `res.end(...)`, including `Content-Type` such as `application/json; charset=utf-8` for JSON APIs.
150-
- **Handle CORS headers**. Browsers block cross-origin requests without proper CORS headers. Default to allowing all origins for simple APIs:
151-
- Respond to `OPTIONS` preflight with `200` and CORS headers
152-
- Include `Access-Control-Allow-Origin: *` (or specific origin) on all responses
150+
- **Handle CORS headers — but first check who terminates CORS.** A function reached through the HTTP gateway must **not** set `Access-Control-Allow-Origin` itself: the gateway already fills it from the environment security-domain allowlist, and a second value yields `<origin>,*`, which browsers reject outright — every request fails with a CORS error that looks like the service is down. Only set CORS headers when the function is called directly, outside the gateway:
151+
- Respond to `OPTIONS` preflight with an empty `204`
152+
- Include `Access-Control-Allow-Origin` only for direct, non-gateway callers
153153
- Include `Access-Control-Allow-Methods: GET, POST, OPTIONS` as needed
154154
- Include `Access-Control-Allow-Headers: Content-Type` for JSON requests
155155
- Keep routing and method handling explicit. Unknown paths should return `404`, and known paths with unsupported methods should normally return `405`.
@@ -259,12 +259,12 @@ exports.main = async (event, context) => {
259259
const http = require("http");
260260
const { URL } = require("url");
261261

262-
// CORS headers — default to * for simple cross-origin APIs
263-
const CORS_HEADERS = {
264-
"Access-Control-Allow-Origin": "*",
265-
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
266-
"Access-Control-Allow-Headers": "Content-Type",
267-
};
262+
// CORS: leave this empty when the function is reached through the HTTP gateway.
263+
// The gateway already fills Access-Control-Allow-Origin from the environment
264+
// security-domain allowlist; adding a second value makes the header illegal
265+
// ('<origin>,*') and browsers block every request. Only set CORS headers here
266+
// when the function is called directly, outside the gateway.
267+
const CORS_HEADERS = {};
268268

269269
function sendJson(res, statusCode, data) {
270270
res.writeHead(statusCode, {

‎skills/cloud-functions/references/http-functions.md‎

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ If the user specifies "Node.js 18", use runtime `Nodejs18.15` and the path `/var
5252
const http = require("http");
5353
const { URL } = require("url");
5454

55-
// CORS headers — default to * for simple cross-origin APIs
56-
const CORS_HEADERS = {
57-
"Access-Control-Allow-Origin": "*",
58-
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
59-
"Access-Control-Allow-Headers": "Content-Type",
60-
};
55+
// CORS: leave this empty when the function is reached through the HTTP gateway.
56+
// The gateway already fills Access-Control-Allow-Origin from the environment
57+
// security-domain allowlist; adding a second value makes the header illegal
58+
// ('<origin>,*') and browsers block every request. Only set CORS headers here
59+
// when the function is called directly, outside the gateway.
60+
const CORS_HEADERS = {};
6161

6262
function sendJson(res, statusCode, data) {
6363
res.writeHead(statusCode, {
@@ -134,7 +134,7 @@ server.listen(9000);
134134
- If you intentionally use ES Modules, use `import ...` consistently and do not rely on CommonJS-only globals such as bare `__dirname`, `require(...)`, or `module.exports`. When you need the current file path in ESM, derive it from `import.meta.url`.
135135
- Treat routing, method checks, and body parsing as part of the function code. With the native `http` module, parse `req.url` yourself and read the request body from the stream before calling `JSON.parse`.
136136
- Return JSON responses explicitly and set `Content-Type` yourself, for example `application/json; charset=utf-8`.
137-
- **Handle CORS headers**. Browsers block cross-origin requests without proper CORS headers. Default to `Access-Control-Allow-Origin: *` for simple APIs, and always respond to `OPTIONS` preflight requests with `200` and CORS headers.
137+
- **Handle CORS headers — but first check who terminates CORS.** A function reached through the HTTP gateway must **not** set `Access-Control-Allow-Origin` itself: the gateway already fills it from the environment security-domain allowlist, and an extra value yields `<origin>,*`, which browsers reject outright — every request fails with a CORS error that looks like the service is down. Only set CORS headers when the function is called directly, outside the gateway. Either way, make `OPTIONS` preflight return an empty `204`.
138138
- Keep unsupported routes and methods explicit. Return `404` for unknown paths, and return `405` when the path exists but the HTTP method is not allowed.
139139
- Keep `scf_bootstrap`, `index.js`, `package.json`, and any bundled dependencies in the function directory that will be uploaded.
140140
- Keep credentials out of the function package. Inject them through function environment variables and preserve existing variables when updating the configuration.
@@ -164,12 +164,12 @@ That combination avoids the common ESM pitfall where `__dirname` is not defined.
164164
const http = require("http");
165165
const { URL } = require("url");
166166

167-
// CORS headers — default to * for simple cross-origin APIs
168-
const CORS_HEADERS = {
169-
"Access-Control-Allow-Origin": "*",
170-
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
171-
"Access-Control-Allow-Headers": "Content-Type",
172-
};
167+
// CORS: leave this empty when the function is reached through the HTTP gateway.
168+
// The gateway already fills Access-Control-Allow-Origin from the environment
169+
// security-domain allowlist; adding a second value makes the header illegal
170+
// ('<origin>,*') and browsers block every request. Only set CORS headers here
171+
// when the function is called directly, outside the gateway.
172+
const CORS_HEADERS = {};
173173

174174
function sendJson(res, statusCode, data) {
175175
res.writeHead(statusCode, {
@@ -266,8 +266,8 @@ Follow these steps in order when creating a managed-runtime HTTP Function:
266266
1. **Write the function code** — create the directory with `index.js`, `scf_bootstrap`, and `package.json`.
267267
2. **Configure SDK credentials when needed** — if the function uses `@cloudbase/node-sdk` or `@cloudbase/manager-node`, follow `./http-function-credentials.md`. For a Node SDK server API Key, use `manageAppAuth(action="createApiKey", keyType="api_key")` and inject `CLOUDBASE_APIKEY`. Manager SDK requires Tencent Cloud `SecretId` / `SecretKey`.
268268
3. **Deploy with `manageFunctions`** — set `type: "HTTP"`, `protocolType: "HTTP"`, and `runtime` explicitly.
269-
4. **Configure security rules** — HTTP Functions default to a restrictive security rule. If the function should be publicly accessible, call `managePermissions(action="updateResourcePermission")` with `resourceType="function"`. Note: anonymous login is disabled by default for new environments; use `permission: "CUSTOM"` with `securityRule: '{"invoke":"true"}'` for truly public endpoints rather than relying on anonymous auth.
270-
5. **Verify** — call the function URL and confirm it returns the expected response. If the function uses a CloudBase SDK, exercise one harmless SDK read and check logs for expired-token or authorization failures. If you get `EXCEED_AUTHORITY` at invocation, the function security rule needs to be updated (step 4).
269+
4. **Choose how the function is reached — gateway route first.** Anything a browser, game client or mobile app calls should go through a gateway route (`manageGateway(action="createRoute", upstreamResourceType="WEB_SCF", path="/api/...")`): it is per-route, it needs no change to the environment-wide authorization document, and the gateway handles CORS for you. Only when the `/v1/functions/<name>` platform path itself must accept callers should you change the function security rule — read "Security rule configuration" first for the PostgreSQL caveat.
270+
5. **Verify against the real entry point** — the gateway route for browser/public access, the platform path with a credential otherwise. Failures come in two distinct shapes: **no credential at all → `401 MISSING_CREDENTIALS`**; **credential present but not allowed → `403 EXCEED_AUTHORITY`** (that one means the security rule needs updating, step 4). If the function uses a CloudBase SDK, exercise one harmless SDK read and check logs for expired-token or authorization failures.
271271

272272
## Deployment flow
273273

@@ -296,11 +296,13 @@ manageFunctions({
296296

297297
### Security rule configuration
298298

299-
After creating an HTTP Function, it will reject unauthenticated callers with `EXCEED_AUTHORITY` by default. If the function should be publicly accessible:
299+
After creating an HTTP Function, a call with no credential fails with `401 MISSING_CREDENTIALS`, and a call that carries a credential but is not allowed fails with `403 EXCEED_AUTHORITY`. If the function should be publicly accessible, **prefer a gateway route** ("HTTP access path for browser/public access" below) and only touch the rule when the platform path itself must accept callers:
300300

301301
> ⚠️ **Note:** Anonymous login is disabled by default for new environments. For public endpoints, use `rule: "true"` to allow all callers regardless of auth state, rather than relying on anonymous login being enabled.
302302
>
303303
> ⚠️ **PostgreSQL environments:** platform `ModifyResourcePermission` / `DescribeResourcePermission` reject PG envs. Current MCP aligns with CLI `tcb policy set/get`: `managePermissions` / `queryPermissions` for `resourceType="function"` automatically fall back to Manager SDK `modifyEnvAuthzConfig` / `describeEnvAuthzConfig` (`authz.user.rego`). Passing `securityRule: '{"invoke":true}'` generates a public-functions OPA allow policy; you can also pass a full Rego document starting with `package authz.user`. See https://docs.cloudbase.net/cli-v1/policy/management
304+
>
305+
> ⚠️ **This document is environment-wide, not per-function.** Writing it replaces the policy for the **whole environment**, so any allow rule another owner already configured is silently dropped. In a shared environment, read the current document first (`queryPermissions` / `describeEnvAuthzConfig`) and prefer a gateway route (`auth: false`) instead of editing it.
304306
305307
```javascript
306308
managePermissions({
@@ -337,14 +339,14 @@ manageFunctions({
337339

338340
## Invocation options
339341

340-
### HTTP API with token
342+
### Platform path with a credential (server-to-server only)
341343

342344
```bash
343345
curl -L "https://{envId}.api.tcloudbasegateway.com/v1/functions/{name}?webfn=true" \
344346
-H "Authorization: Bearer <TOKEN>"
345347
```
346348

347-
This is suitable for authenticated server-to-server access.
349+
This path always wants a credential: with none it returns `401 MISSING_CREDENTIALS`, with a front-end-safe publishable key it returns `403 EXCEED_AUTHORITY`, and it only succeeds with an admin (`service_role`) credential. **Do not hand this path — or an admin key — to browser or client code.** Browser, game and mobile clients use the gateway route described next.
348350

349351
### HTTP access path for browser/public access
350352

‎skills/postgresql-development-cloudbase/SKILL.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ Hard rule: never let an upload error be silently swallowed. If `uploadCoverImage
302302

303303
- PG HTTP API is in the CloudBase relational database HTTP API family, together with MySQL. In MCP docs/search this appears under `mysqldb`.
304304
- Before writing raw `fetch()` code, query OpenAPI docs: `searchKnowledgeBase(mode="openapi", apiName="mysqldb", query="PostgreSQL fetch insert update rpc")`.
305-
- Do not construct `/api/v1/rdb/rest` or `/api/v1/rdb/rest/rpc` from memory. A guessed path that returns 404 is a hard blocker; switch back to JS SDK v3 or read the OpenAPI contract.
305+
- Do not construct the REST paths from memory. A guessed path that returns 404 is a hard blocker; read the OpenAPI contract for table endpoints (`fetch` / `insert` / `update` / `delete`).
306+
- **Database functions (RPC)** are how you perform an atomic server-side operation — a guarded counter, a conditional update, a multi-step write — that a plain REST update cannot express safely. The endpoint is `POST /v1/rdb/rest/rpc/<function>` on the same gateway base as the table endpoints; it is **not** part of the `mysqldb` OpenAPI document, so confirm it with one live call before writing it into code.
306307
- If environment variables expose `TCB_HTTP_API_BASE_URL` / `VITE_TCB_HTTP_API_BASE_URL`, treat them as the base only. The path, method, headers, and auth model must still come from OpenAPI docs or an existing working helper.
307308

308309
## Frontend Guardrails

0 commit comments

Comments
 (0)