@clawos-dev/clawd 0.2.540 → 0.2.542
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/dist/cli.cjs +8 -7
- package/dist/deploy-kit/.secrets/aliyun.env.example +5 -2
- package/dist/deploy-kit/.secrets/aliyun.env.local.example +7 -10
- package/dist/deploy-kit/scripts/ensure-credentials.sh +21 -21
- package/dist/deploy-kit/scripts/ensure-credentials.spec.ts +31 -17
- package/dist/deploy-kit/scripts/publish.sh +1 -1
- package/dist/deploy-kit/scripts/remove-extension.sh +1 -1
- package/dist/persona-defaults/persona-app-builder/.mcp.json +1 -1
- package/dist/persona-defaults/persona-app-builder/CLAUDE.md +9 -8
- package/dist/persona-defaults/persona-app-builder/extension-kit/README.md +2 -2
- package/dist/persona-defaults/persona-app-builder/extension-kit/examples/nestjs-react/server/.env.example +1 -1
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/README.md +2 -2
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/config.env +1 -1
- package/dist/secrets/README.md +36 -18
- package/dist/secrets/supabase.env.example +17 -0
- package/package.json +1 -1
- package/dist/deploy-kit/.secrets/aliyun.env +0 -7
- package/dist/secrets/supabase.env +0 -16
package/dist/cli.cjs
CHANGED
|
@@ -50195,11 +50195,12 @@ var DEFAULT_PERSONAS = [
|
|
|
50195
50195
|
// 与 app-builder 对齐"调用阿里云的工作方式"(owner 2026-06-17 要求):开发型 profile —— 放开文件/web
|
|
50196
50196
|
// 工具 + node/pnpm 工具链精确路径 + 出站 TLD 通配白名单。html-slides 需要联网(git clone frontend-slides
|
|
50197
50197
|
// skill、调阿里云 CLI/SDK)。
|
|
50198
|
-
// 阿里云凭证:**复用共享 deploy-kit 单源**($HOME/.clawd/deploy-kit/.secrets/aliyun.env
|
|
50199
|
-
//
|
|
50200
|
-
//
|
|
50201
|
-
// deploy-kit/.secrets/aliyun.env; set +a`
|
|
50202
|
-
//
|
|
50198
|
+
// 阿里云凭证:**复用共享 deploy-kit 单源**($HOME/.clawd/deploy-kit/.secrets/aliyun.env.local,使用者自己写、
|
|
50199
|
+
// 全 FC persona 共用;bundle 不再 ship AK,见 specs/2026-09-18-aliyun-ak-leak-rotate-design.md),不在 persona
|
|
50200
|
+
// 目录另存一份。app-builder 的 FC 部署走 daemon 侧脚本(沙箱外)故其 profile 无需 carve 这个路径;html-slides
|
|
50201
|
+
// 没有 daemon 侧流程、要在 cc 沙箱内直接 `set -a; . $HOME/.clawd/deploy-kit/.secrets/aliyun.env.local; set +a`
|
|
50202
|
+
// 后调 aliyun CLI(env 凭证绕过沙箱外的 ~/.aliyun/),所以这里**额外**把这两个凭证文件加进 allowRead
|
|
50203
|
+
// (denyRead '~/' 之上的精确凿洞,单文件、最小暴露,同 ~/.npmrc 先例;aliyun.env 是老机器上的遗留文件)。
|
|
50203
50204
|
// excludedCommands: ['aliyun *'] —— 额外把 aliyun CLI 放沙箱外跑(逃出 seatbelt 直接用宿主凭证/网络),
|
|
50204
50205
|
// 与上面沙箱内 env 凭证方案并存,按运行时实际命令前缀匹配生效。
|
|
50205
50206
|
sandboxProfile: {
|
|
@@ -50209,7 +50210,7 @@ var DEFAULT_PERSONAS = [
|
|
|
50209
50210
|
},
|
|
50210
50211
|
sandbox: {
|
|
50211
50212
|
filesystem: {
|
|
50212
|
-
allowRead: ["~/.npmrc", "~/Library/Preferences/pnpm", "~/.nvm", "~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store", "~/.clawd/deploy-kit/.secrets/aliyun.env"],
|
|
50213
|
+
allowRead: ["~/.npmrc", "~/Library/Preferences/pnpm", "~/.nvm", "~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store", "~/.clawd/deploy-kit/.secrets/aliyun.env", "~/.clawd/deploy-kit/.secrets/aliyun.env.local"],
|
|
50213
50214
|
allowWrite: ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"]
|
|
50214
50215
|
},
|
|
50215
50216
|
network: {
|
|
@@ -70910,7 +70911,7 @@ function computeMethodAccess(args) {
|
|
|
70910
70911
|
}
|
|
70911
70912
|
|
|
70912
70913
|
// src/version.ts
|
|
70913
|
-
var version = "0.2.
|
|
70914
|
+
var version = "0.2.542".length > 0 ? "0.2.542" : "dev";
|
|
70914
70915
|
|
|
70915
70916
|
// src/cli-probe/probe.ts
|
|
70916
70917
|
var fs78 = __toESM(require("fs"), 1);
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
#
|
|
2
|
-
# aliyun.env
|
|
1
|
+
# 阿里云 RAM AccessKey(publish.sh / remove-extension.sh 经 ensure-credentials.sh source)。
|
|
2
|
+
# clawd 不随包 ship 任何一把 AK:把自己的 AK/SK 写进同目录的 aliyun.env.local(推荐,永不被 OTA 覆盖)
|
|
3
|
+
# 或 aliyun.env;两个都不进 git(clawd/.gitignore 只放行 *.example)。云上不用文件,gateway 经 env 注入。
|
|
4
|
+
# 需要权限(按 90 天 ActionTrail 反推):FC(cn-hangzhou)+ SLS 的 serverless-cn-hangzhou-* project + 证书只读;
|
|
5
|
+
# 没见到 OSS 调用(大代码包是否走 OSS 中转未验证,缺了 s deploy 会在 ActionTrail 里报 NoPermission)。
|
|
3
6
|
ALIBABA_CLOUD_ACCESS_KEY_ID=replace-me
|
|
4
7
|
ALIBABA_CLOUD_ACCESS_KEY_SECRET=replace-me
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
# 阿里云 RAM AccessKey
|
|
1
|
+
# 阿里云 RAM AccessKey(本机专用)
|
|
2
2
|
#
|
|
3
|
-
# 复制这份为同目录下 aliyun.env.local,填自己的 AK/SK
|
|
4
|
-
# source
|
|
3
|
+
# 复制这份为同目录下 aliyun.env.local,填自己的 AK/SK。publish.sh / remove-extension.sh 会依次
|
|
4
|
+
# source aliyun.env(如果有)→ aliyun.env.local,后者的值覆盖前者。
|
|
5
5
|
#
|
|
6
|
-
# .local 后缀由 daemon refreshDeployKit 特判:**永远不会被 OTA
|
|
7
|
-
# (每次 daemon 启动会被 defaults 里的新版覆盖)是两回事。
|
|
6
|
+
# .local 后缀由 daemon refreshDeployKit 特判:**永远不会被 OTA 覆盖**。
|
|
8
7
|
#
|
|
9
|
-
#
|
|
10
|
-
# -
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# 不需要用 .local 时(大部分情况):删掉这个 .local 文件、直接跑 clawd defaults,OTA 后自动拿到新 demo 凭证。
|
|
8
|
+
# 2026-09-18 起 clawd 不再随包 ship 共享 demo AK(上一把随 npm 包发出去 69 秒就被 TruffleHog 收割,
|
|
9
|
+
# 主账号被阿里云风控锁;见 specs/2026-09-18-aliyun-ak-leak-rotate-design.md)——本机发布必须配这份。
|
|
10
|
+
# 老机器上 OTA 留下的 aliyun.env 里那把 AK 已泄露、不可再用,不用删,配了 .local 就会盖过它。
|
|
14
11
|
ALIBABA_CLOUD_ACCESS_KEY_ID=replace-me
|
|
15
12
|
ALIBABA_CLOUD_ACCESS_KEY_SECRET=replace-me
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
# 被 `source` 进来,再调 ensure_credentials。跟 ensure-toolchain.sh 是一对:
|
|
5
5
|
# 那个管「命令在不在」,这个管「命令拿什么身份跑」。
|
|
6
6
|
#
|
|
7
|
-
# 硬约束:**全程不碰用户全局 ~/.s**。clawd 发布用的是
|
|
8
|
-
#
|
|
9
|
-
#
|
|
7
|
+
# 硬约束:**全程不碰用户全局 ~/.s**。clawd 发布用的是 deploy-kit 自己那份 AK(本机 .secrets/
|
|
8
|
+
# 下使用者写的文件,云上是 gateway 注入的 env),而 ~/.s/access.yaml 里的 default 是用户自己账号的
|
|
9
|
+
# Serverless Devs 凭证——它是用户的东西,不是我们的。做法对齐本 kit 处理 aliyun CLI 的方式(凭证只进本次进程的 env,
|
|
10
10
|
# 全局 ~/.aliyun/ 一个字节不碰):把 Serverless Devs 的配置家目录整个指到 deploy-kit
|
|
11
11
|
# 名下,access.yaml 写在那里。
|
|
12
12
|
# ============================================================
|
|
@@ -18,27 +18,27 @@
|
|
|
18
18
|
# 里的 access 字段,本改动前 scaffold 的老项目(s.yaml 写着 default)照样走这条。
|
|
19
19
|
S_ACCESS_ALIAS=clawd-fc
|
|
20
20
|
|
|
21
|
-
# 分层加载阿里云 AK 进 env
|
|
21
|
+
# 分层加载阿里云 AK 进 env,三层平铺、后读的覆盖先读的:
|
|
22
|
+
# 1. `$KIT_DIR/.secrets/aliyun.env` —— 使用者自己写的(或 2026-09-18 之前 OTA 留下的旧文件);
|
|
23
|
+
# 2. `$KIT_DIR/.secrets/aliyun.env.local` —— 使用者自己写的,refreshDeployKit 永不覆盖;
|
|
24
|
+
# 3. 进程 env 里已有的 `ALIBABA_CLOUD_ACCESS_KEY_ID/_SECRET` —— 云上容器那条路:Pod 里没有
|
|
25
|
+
# `.secrets/`(`cloud-host/provision/build-image.mjs` 刻意把它剔出镜像层——镜像要分发,凭据
|
|
26
|
+
# 进层就洗不掉了),AK 由 gateway 经 **MCP server 的 per-server env** 交到调用本脚本的那个
|
|
27
|
+
# 进程里(M1b Step 9)。不落盘是有意的:写成文件的话 agent 一个 `cat` 就看见了。
|
|
22
28
|
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
# - 云上容器:没有 `.secrets/`(`cloud-host/provision/build-image.mjs` 刻意把它剔出镜像层
|
|
26
|
-
# ——镜像要分发,凭据进层就洗不掉了),AK 由 gateway 经 **MCP server 的 per-server env**
|
|
27
|
-
# 交到调用本脚本的那个进程里(M1b Step 9)。这条分支不落盘是有意的:写成文件的话
|
|
28
|
-
# agent 一个 `cat` 就看见了,而 env 只有这个子进程有。
|
|
29
|
+
# clawd **不再随包 ship 任何一把 AK**(2026-09-18 起,见 specs/2026-09-18-aliyun-ak-leak-rotate-design.md:
|
|
30
|
+
# 上一把随 npm 包发出去 69 秒就被 TruffleHog 收割,主账号被风控锁)。三层都空 = 使用者还没配,fail-loud。
|
|
29
31
|
ensure_aliyun_env() {
|
|
30
32
|
local kit="${KIT_DIR:?ensure_aliyun_env 需要调用方先设 KIT_DIR}"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
set -a; . "$kit/.secrets/aliyun.env.local"; set +a
|
|
33
|
+
local f
|
|
34
|
+
# 写成 if 而不是 `[ -f ] && { }`:后者在函数末尾会把「文件不存在」变成函数返回 1,调用方 set -e 直接中止。
|
|
35
|
+
for f in "$kit/.secrets/aliyun.env" "$kit/.secrets/aliyun.env.local"; do
|
|
36
|
+
if [ -f "$f" ]; then
|
|
37
|
+
set -a; . "$f"; set +a
|
|
37
38
|
fi
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
echo "❌ 缺 $kit/.secrets/aliyun.env(clawd ship 的共享 demo 凭证,OTA 自动刷新),env 里也没有 ALIBABA_CLOUD_ACCESS_KEY_ID/_SECRET。参考 .secrets/aliyun.env.example 填写。" >&2
|
|
39
|
+
done
|
|
40
|
+
if [ -z "${ALIBABA_CLOUD_ACCESS_KEY_ID:-}" ] || [ -z "${ALIBABA_CLOUD_ACCESS_KEY_SECRET:-}" ]; then
|
|
41
|
+
echo "❌ 没有阿里云 AK:把自己的 AK/SK 写进 $kit/.secrets/aliyun.env.local(参考同目录 aliyun.env.local.example;这个文件不会被 OTA 覆盖),云上则由 gateway 经 env 注入。" >&2
|
|
42
42
|
return 1
|
|
43
43
|
fi
|
|
44
44
|
export ALIBABA_CLOUD_REGION_ID="${REGION:?config.env 缺 REGION}"
|
|
@@ -80,7 +80,7 @@ ensure_s_access() {
|
|
|
80
80
|
# 把 CLI 原文摆出来,让读的人按原文判断。
|
|
81
81
|
echo "❌ aliyun sts GetCallerIdentity 失败,拿不到 AccountId。aliyun 原文:" >&2
|
|
82
82
|
echo "$ident" >&2
|
|
83
|
-
echo " 排查顺序:① 上面这行 CLI 原文说的是什么 ② $kit/.secrets/aliyun.env
|
|
83
|
+
echo " 排查顺序:① 上面这行 CLI 原文说的是什么 ② $kit/.secrets/aliyun.env.local(或 aliyun.env)里的 AK 是否有效——2026-09-18 之前 OTA 发的那把已泄露、不可再用,得换自己的 ③ config.env 的 REGION" >&2
|
|
84
84
|
return 1
|
|
85
85
|
}
|
|
86
86
|
# 用 node 不用 python3:目标机器保证有 node(clawd 本身就是 node 跑的),不保证有 python
|
|
@@ -78,11 +78,12 @@ beforeEach(() => {
|
|
|
78
78
|
mkdirSync(join(home, '.s'), { recursive: true })
|
|
79
79
|
mkdirSync(bin, { recursive: true })
|
|
80
80
|
|
|
81
|
-
// 真脚本进沙箱 kit
|
|
81
|
+
// 真脚本进沙箱 kit。.secrets 按生产形状:bundle 只带 *.example(2026-09-18 起 AK 不再随包
|
|
82
|
+
// 分发,见 specs/2026-09-18-aliyun-ak-leak-rotate-design.md),本机凭证是使用者自己写的 .local。
|
|
82
83
|
cpSync(SCRIPTS_DIR, join(kit, 'scripts'), { recursive: true })
|
|
83
84
|
writeFileSync(
|
|
84
|
-
join(kit, '.secrets', 'aliyun.env'),
|
|
85
|
-
'ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI-
|
|
85
|
+
join(kit, '.secrets', 'aliyun.env.local'),
|
|
86
|
+
'ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI-MY-OWN\nALIBABA_CLOUD_ACCESS_KEY_SECRET=my-own-secret\n',
|
|
86
87
|
)
|
|
87
88
|
writeFileSync(join(home, '.s', 'access.yaml'), USER_ACCESS_YAML)
|
|
88
89
|
writeAliyunShim(bin)
|
|
@@ -127,8 +128,8 @@ describe('ensure_credentials', () => {
|
|
|
127
128
|
runInKit('ensure_credentials')
|
|
128
129
|
const yaml = kitAccessYaml()
|
|
129
130
|
expect(yaml).toContain("AccountID: '5566778899001122'")
|
|
130
|
-
expect(yaml).toContain('AccessKeyID: LTAI-
|
|
131
|
-
expect(yaml).toContain('AccessKeySecret:
|
|
131
|
+
expect(yaml).toContain('AccessKeyID: LTAI-MY-OWN')
|
|
132
|
+
expect(yaml).toContain('AccessKeySecret: my-own-secret')
|
|
132
133
|
})
|
|
133
134
|
|
|
134
135
|
it('profile 名是 clawd-fc 而不是 default', () => {
|
|
@@ -151,14 +152,26 @@ describe('ensure_credentials', () => {
|
|
|
151
152
|
expect(mode.toString(8)).toBe('600')
|
|
152
153
|
})
|
|
153
154
|
|
|
154
|
-
|
|
155
|
+
// 存量机器:OTA 停发 aliyun.env 之后 refreshDeployKit 不再覆盖也不删它,旧文件会留在盘上。
|
|
156
|
+
// 有 .local 时 .local 必须盖过它(否则老用户配了自己的 AK 还在用那把已停用的)。
|
|
157
|
+
it('legacy aliyun.env 仍被读,但 .local 覆盖它', () => {
|
|
155
158
|
writeFileSync(
|
|
156
|
-
join(box.kit, '.secrets', 'aliyun.env
|
|
157
|
-
'ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI-
|
|
159
|
+
join(box.kit, '.secrets', 'aliyun.env'),
|
|
160
|
+
'ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI-STALE-OTA\nALIBABA_CLOUD_ACCESS_KEY_SECRET=stale-ota-secret\n',
|
|
158
161
|
)
|
|
159
162
|
runInKit('ensure_credentials')
|
|
160
163
|
expect(kitAccessYaml()).toContain('AccessKeyID: LTAI-MY-OWN')
|
|
161
|
-
expect(kitAccessYaml()).toContain('
|
|
164
|
+
expect(kitAccessYaml()).not.toContain('LTAI-STALE-OTA')
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('只有 aliyun.env 没有 .local 也能用(使用者直接写 aliyun.env 的老习惯)', () => {
|
|
168
|
+
rmSync(join(box.kit, '.secrets', 'aliyun.env.local'))
|
|
169
|
+
writeFileSync(
|
|
170
|
+
join(box.kit, '.secrets', 'aliyun.env'),
|
|
171
|
+
'ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI-PLAIN-FILE\nALIBABA_CLOUD_ACCESS_KEY_SECRET=plain-file-secret\n',
|
|
172
|
+
)
|
|
173
|
+
runInKit('ensure_credentials')
|
|
174
|
+
expect(kitAccessYaml()).toContain('AccessKeyID: LTAI-PLAIN-FILE')
|
|
162
175
|
})
|
|
163
176
|
|
|
164
177
|
it('调 aliyun 时显式传 AK 和 region,不靠环境变量的隐式优先级', () => {
|
|
@@ -169,8 +182,8 @@ describe('ensure_credentials', () => {
|
|
|
169
182
|
writeAliyunShim(box.bin, '5566778899001122', log)
|
|
170
183
|
runInKit('ensure_credentials')
|
|
171
184
|
const argv = readFileSync(log, 'utf8')
|
|
172
|
-
expect(argv).toContain('--access-key-id LTAI-
|
|
173
|
-
expect(argv).toContain('--access-key-secret
|
|
185
|
+
expect(argv).toContain('--access-key-id LTAI-MY-OWN')
|
|
186
|
+
expect(argv).toContain('--access-key-secret my-own-secret')
|
|
174
187
|
expect(argv).toContain('--region cn-hangzhou')
|
|
175
188
|
})
|
|
176
189
|
|
|
@@ -182,17 +195,17 @@ describe('ensure_credentials', () => {
|
|
|
182
195
|
expect(kitAccessYaml()).toContain("AccountID: '5566778899001122'")
|
|
183
196
|
})
|
|
184
197
|
|
|
185
|
-
it('
|
|
186
|
-
rmSync(join(box.kit, '.secrets', 'aliyun.env'))
|
|
187
|
-
expect(() => runInKit('ensure_credentials')).toThrow()
|
|
198
|
+
it('aliyun.env / .local 都没有、env 里也没有 AK 时 fail-loud,文案指到 .local', () => {
|
|
199
|
+
rmSync(join(box.kit, '.secrets', 'aliyun.env.local'))
|
|
200
|
+
expect(() => runInKit('ensure_credentials')).toThrow(/aliyun\.env\.local/)
|
|
188
201
|
expect(existsSync(join(box.kit, '.s-home', '.s', 'access.yaml'))).toBe(false)
|
|
189
202
|
})
|
|
190
203
|
|
|
191
204
|
// 云上分支(persona 上云 M1b Step 9):容器里没有 `.secrets/`——`build-image.mjs` 刻意把它
|
|
192
205
|
// 剔出镜像层(镜像要分发,凭据进层洗不掉)。AK 由 gateway 经 **MCP server 的 per-server env**
|
|
193
206
|
// 交到调用本脚本的那个子进程里,不落文件:写成文件的话 agent 一个 `cat` 就看见了。
|
|
194
|
-
it('没有 .secrets/
|
|
195
|
-
rmSync(join(box.kit, '.secrets', 'aliyun.env'))
|
|
207
|
+
it('没有 .secrets/ 凭证文件但 env 里有 AK 时用 env(云上容器那条路)', () => {
|
|
208
|
+
rmSync(join(box.kit, '.secrets', 'aliyun.env.local'))
|
|
196
209
|
const out = execFileSync(
|
|
197
210
|
'bash',
|
|
198
211
|
[
|
|
@@ -221,7 +234,7 @@ printf 'ok %s\\n' "$ALIBABA_CLOUD_ACCESS_KEY_ID"`,
|
|
|
221
234
|
expect(userAccessYaml()).toContain('LTAI-USER-OWN-KEY')
|
|
222
235
|
})
|
|
223
236
|
|
|
224
|
-
it('文件在就优先用文件(云上那条只是兜底,不能反过来盖掉本机
|
|
237
|
+
it('文件在就优先用文件(云上那条只是兜底,不能反过来盖掉本机 .local 凭证)', () => {
|
|
225
238
|
const out = execFileSync(
|
|
226
239
|
'bash',
|
|
227
240
|
[
|
|
@@ -244,6 +257,7 @@ printf 'id=%s\\n' "$ALIBABA_CLOUD_ACCESS_KEY_ID"`,
|
|
|
244
257
|
encoding: 'utf8',
|
|
245
258
|
},
|
|
246
259
|
)
|
|
260
|
+
expect(out).toContain('id=LTAI-MY-OWN')
|
|
247
261
|
expect(out).not.toContain('LTAI-FROM-ENV')
|
|
248
262
|
})
|
|
249
263
|
})
|
|
@@ -58,7 +58,7 @@ if ! grep -qxF 's.*.yaml' "$EXT_DIR/.gitignore" 2>/dev/null; then
|
|
|
58
58
|
echo " 📝 .gitignore 补 s.*.yaml (渲出的 s.int.yaml / s.prod.yaml 含 key,不进仓库;记得把 .gitignore 推上去)"
|
|
59
59
|
fi
|
|
60
60
|
|
|
61
|
-
# 2) 工具链 +
|
|
61
|
+
# 2) 工具链 + 阿里云凭证(使用者自己的 .secrets/aliyun.env.local,云上是 env;见 ensure-credentials.sh)
|
|
62
62
|
source "$KIT_DIR/scripts/ensure-toolchain.sh"
|
|
63
63
|
ensure_toolchain
|
|
64
64
|
source "$KIT_DIR/scripts/ensure-credentials.sh"
|
|
@@ -28,7 +28,7 @@ TABLE_PREFIX_INT="${TABLE_PREFIX}int_"
|
|
|
28
28
|
source "$KIT_DIR/scripts/ensure-toolchain.sh"
|
|
29
29
|
ensure_toolchain
|
|
30
30
|
|
|
31
|
-
#
|
|
31
|
+
# 阿里云凭证(使用者自己的 .secrets/aliyun.env.local,云上是 env)+ deploy-kit 私有的 s profile
|
|
32
32
|
source "$KIT_DIR/scripts/ensure-credentials.sh"
|
|
33
33
|
ensure_credentials
|
|
34
34
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_comment": "preinstall ship 进 daemon defaults,daemon 启动时 refreshDaemonManagedDirs 把这文件同步到 ~/.clawd*/personas/persona-app-builder/.mcp.json。**这里只有声明,没有值**:`${VAR}` 占位由 daemon 在 spawn 时从凭据表渲进 per-server env / headers(见 daemon/src/persona/mcp-secret-render.ts),渲染产物是另一份 0600 文件、同名 server 压过本文件,所以 agent 在 persona 目录里读不到任何 key。supabase:用 @aliyun-rds/supabase-mcp-server Mode 2 单实例直连(不再用 aliyun AK),底下接阿里云托管 supabase。这三个 env 名不是我们发明的——该包的 commander option 默认值就取 process.env.SUPABASE_URL / SUPABASE_ANON_KEY / SUPABASE_SERVICE_ROLE_KEY,所以不再传 --supabase-* CLI 参数(参数会进 ps 输出,等于没藏)。**不要往这里加 --jwt-secret / SUPABASE_AUTH_JWT_SECRET**:jwt-secret 是该实例的 JWT 签发密钥,拿到它可以自签任意 role/任意 user 的 token(含 service_role),下发出去等于把 anon/service key 的轮换能力一起交出去;而 MCP server 里它唯一的用处是 verify_jwt_secret 这个自检工具报个 found/preview。github:GitHub 官方远程 MCP(spec 2026-09-14-app-builder-github-mcp-design),建仓 / 提交文件都由 agent 按 .claude/skills/app-builder-projects 走它,本机不再依赖 gh CLI。Authorization 走 `${GITHUB_TOKEN}` 占位而不是留空让 Claude Code 自己 OAuth:没占位的 http server 不进 daemon 的渲染产物,只剩 cwd 里这份项目级声明,daemon 起的 headless 会话过不了 Claude Code 的「项目 MCP 待批准」和交互式 OAuth 两关(2026-09-14 实测)。`GITHUB_TOKEN` 是保留变量名 = 当前用户的 GitHub 身份(spec 2026-09-15-github-auth-unify §4.1):本机由 daemon 从机器级身份(设置 → 账号关联,存在 git 的凭据存储;~/.clawd/secrets/github.env 是 git 没配 helper 时的退路)渲进产物;云上由中心从使用者的 GitHub 身份供值、代理时注 Bearer,不填 PAT
|
|
2
|
+
"_comment": "preinstall ship 进 daemon defaults,daemon 启动时 refreshDaemonManagedDirs 把这文件同步到 ~/.clawd*/personas/persona-app-builder/.mcp.json。**这里只有声明,没有值**:`${VAR}` 占位由 daemon 在 spawn 时从凭据表渲进 per-server env / headers(见 daemon/src/persona/mcp-secret-render.ts),渲染产物是另一份 0600 文件、同名 server 压过本文件,所以 agent 在 persona 目录里读不到任何 key。supabase:用 @aliyun-rds/supabase-mcp-server Mode 2 单实例直连(不再用 aliyun AK),底下接阿里云托管 supabase。这三个 env 名不是我们发明的——该包的 commander option 默认值就取 process.env.SUPABASE_URL / SUPABASE_ANON_KEY / SUPABASE_SERVICE_ROLE_KEY,所以不再传 --supabase-* CLI 参数(参数会进 ps 输出,等于没藏)。**不要往这里加 --jwt-secret / SUPABASE_AUTH_JWT_SECRET**:jwt-secret 是该实例的 JWT 签发密钥,拿到它可以自签任意 role/任意 user 的 token(含 service_role),下发出去等于把 anon/service key 的轮换能力一起交出去;而 MCP server 里它唯一的用处是 verify_jwt_secret 这个自检工具报个 found/preview。github:GitHub 官方远程 MCP(spec 2026-09-14-app-builder-github-mcp-design),建仓 / 提交文件都由 agent 按 .claude/skills/app-builder-projects 走它,本机不再依赖 gh CLI。Authorization 走 `${GITHUB_TOKEN}` 占位而不是留空让 Claude Code 自己 OAuth:没占位的 http server 不进 daemon 的渲染产物,只剩 cwd 里这份项目级声明,daemon 起的 headless 会话过不了 Claude Code 的「项目 MCP 待批准」和交互式 OAuth 两关(2026-09-14 实测)。`GITHUB_TOKEN` 是保留变量名 = 当前用户的 GitHub 身份(spec 2026-09-15-github-auth-unify §4.1):本机由 daemon 从机器级身份(设置 → 账号关联,存在 git 的凭据存储;~/.clawd/secrets/github.env 是 git 没配 helper 时的退路)渲进产物;云上由中心从使用者的 GitHub 身份供值、代理时注 Bearer,不填 PAT。值不随 OTA 下发(本机 ~/.clawd/secrets/supabase.env,云上 gateway 注入),来龙去脉见 doc/glossary/persona-cloud.md。",
|
|
3
3
|
"mcpServers": {
|
|
4
4
|
"github": {
|
|
5
5
|
"type": "http",
|
|
@@ -92,15 +92,15 @@
|
|
|
92
92
|
|
|
93
93
|
## 后端:supabase MCP
|
|
94
94
|
|
|
95
|
-
**`supabase`** —— 后端数据/认证/存储,唯一的 MCP 支柱。这份 Supabase **是阿里云托管 supabase
|
|
95
|
+
**`supabase`** —— 后端数据/认证/存储,唯一的 MCP 支柱。这份 Supabase **是阿里云托管 supabase 实例**(地址就是凭据表里的 `SUPABASE_URL`,你看不到值也不用看),**不是**云上 `supabase.com` 的实例。开工前确认能连上:
|
|
96
96
|
|
|
97
97
|
- 读表结构、跑 SQL、看 auth 用户都走这个 MCP,不要凭记忆猜 schema
|
|
98
|
-
- **凭据值你看不到,也不需要看到**:`extension-kit/config.env` 与 `server/.env.example` 里只有变量名(`${SUPABASE_URL}` / `${SUPABASE_KEY}`),值由 daemon 在起 MCP server 时才注进那个子进程。`createProject` 时 scaffold 会把项目的 `server/.env`
|
|
98
|
+
- **凭据值你看不到,也不需要看到**:`extension-kit/config.env` 与 `server/.env.example` 里只有变量名(`${SUPABASE_URL}` / `${SUPABASE_KEY}`),值由 daemon 在起 MCP server 时才注进那个子进程。`createProject` 时 scaffold 会把项目的 `server/.env` 渲好(前提是这台机器配了凭据表:云上由 gateway 注入,本机要有 `~/.clawd/secrets/supabase.env`;没配会渲成空串并 warn),直接 `pnpm dev` 就能连上——**不要**去别处找 key 往文件里抄
|
|
99
99
|
- **红线**:这是共享生产库。建表 / 迁移前先 `list_tables` 看清现状,新项目的表**必须**带 `TABLE_PREFIX` 沉到 `public` schema(integration 是 `${APP_NAME}_${SLUG}_int_`,prod 是 `${APP_NAME}_${SLUG}_`,如 `helloworld_a1b2_int_click_counter` / `helloworld_a1b2_click_counter`;`APP_NAME` 和 `SLUG` 都从项目 `ext.conf` 读,**不要自己另起一套 slug**),避免和 clawos / 其它项目 / 别人同名 app 的表撞名;**绝不** drop / alter clawos 已有的表,不确定哪些是 clawos 的就先问老板
|
|
100
100
|
- **表两套,DDL 一份**:表结构写在 `server/db/schema.sql`,表名用 `__TABLE_PREFIX__visits` 占位;`node <skill>/scripts/render-sql.mjs --project <projectDir> --env integration` 渲出 SQL 用 supabase MCP `execute_sql` 跑(`apply_migration` 在阿里云自建实例上不可用),在测试地址验过再 `--env prod` 跑一次。server 代码里表名只经 `tableName('visits')`(`server/src/table-name.ts`,读 env `TABLE_PREFIX`),不写死
|
|
101
101
|
- 建了表记得把**基础名**(如 `visits`)填进 `ext.conf` 的 `SUPABASE_TABLES`(空格分隔),`removeProject` 据此打印两套清理语句
|
|
102
102
|
|
|
103
|
-
**易踩的坑**:唯一真源是 **daemon
|
|
103
|
+
**易踩的坑**:唯一真源是 **daemon 的凭据表**(本机 `~/.clawd/secrets/supabase.env`,云上 gateway 经 env 注入;clawd 自带的只有占位模板)—— supabase MCP 连它,`publish.sh` 也把它渲染进 s.yaml 给线上用,scaffold 渲项目 `.env` 还是它。项目 `.env` 被手改成别的地址,就会 **MCP 建表落一台 / server 通过 supabase-js 查另一台**,两边 PostgREST 的 schema cache 各自独立 → `PGRST205 schema cache 找不到表`。看到 PGRST 系列错码,先看项目 `.env` 的 `SUPABASE_URL` 是不是被人动过。
|
|
104
104
|
|
|
105
105
|
## 部署:阿里云 FC(serverless)
|
|
106
106
|
|
|
@@ -111,12 +111,13 @@
|
|
|
111
111
|
- 工具链 `aliyun` CLI + Serverless Devs(`s`)由 `deploy-kit/scripts/ensure-toolchain.sh` 在 publish / remove 前自动检测 + 安装,接管发布失败时**不必再排查「CLI 没装」**
|
|
112
112
|
- 实时推送用 Supabase Realtime(FC 不维持长连接)
|
|
113
113
|
|
|
114
|
-
##
|
|
114
|
+
## 阿里云凭证:使用者自带,放共享 deploy-kit 的 `.secrets/`
|
|
115
115
|
|
|
116
|
-
AK/SK
|
|
116
|
+
clawd **不随包 ship 任何一把 AK**。AK/SK 放在 `$HOME/.clawd/deploy-kit/.secrets/`、全 FC persona 共用,不在系统环境变量里:
|
|
117
117
|
|
|
118
|
-
- **`aliyun.env`** —
|
|
119
|
-
- **`aliyun.env
|
|
118
|
+
- **`aliyun.env.local`** — 使用者自己的 AK,永远不被 OTA 覆盖。复制 `aliyun.env.local.example` → `aliyun.env.local` 填值
|
|
119
|
+
- **`aliyun.env`**(可有可无)— 也会被读,`.local` 覆盖它。老机器上 2026-09-18 之前 OTA 留下的这份里的 AK 已泄露、不可再用
|
|
120
|
+
- 云上没有这两个文件,AK 由 gateway 经 MCP server 的 env 注入
|
|
120
121
|
|
|
121
122
|
手动排障要跑 `aliyun` / `s` 命令时,在**同一条 Bash** 里加载再用(shell 变量不跨调用留存):
|
|
122
123
|
|
|
@@ -129,7 +130,7 @@ aliyun_ak fc GET /2023-03-30/custom-domains # aliyun 一律走 aliyun_a
|
|
|
129
130
|
s deploy -y -t s.int.yaml --access "$S_ACCESS_ALIAS" # s 一律显式带 profile + 指明哪个环境的 s 文件(s.int.yaml / s.prod.yaml)
|
|
130
131
|
```
|
|
131
132
|
|
|
132
|
-
**红线**:绝不写用户全局 `~/.s/access.yaml`(那里是用户自己账号的凭证,盖上去不可恢复);绝不 `echo` / 打印 / 写进日志或提交记录里暴露 SK;绝不把 `.secrets/`
|
|
133
|
+
**红线**:绝不写用户全局 `~/.s/access.yaml`(那里是用户自己账号的凭证,盖上去不可恢复);绝不 `echo` / 打印 / 写进日志或提交记录里暴露 SK;绝不把 `.secrets/` 拷进项目代码;`ensure_credentials` 报「没有阿里云 AK」就停下提醒老板配 `aliyun.env.local`,别自己去找别的 AK 填。
|
|
133
134
|
|
|
134
135
|
## 任务分级与节奏
|
|
135
136
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
FC 对应用只有一条要求:**一个监听 `$PORT` 的 HTTP server**。所以固化的是「发布管道」,不是技术栈。
|
|
8
8
|
|
|
9
|
-
- **共享 deploy-kit(凭证 + 脚本骨架 + bootstrap,全 FC persona 一份)**:`$HOME/.clawd/deploy-kit/`(`scripts/` + `contract/bootstrap` + `.secrets/aliyun.env`)
|
|
9
|
+
- **共享 deploy-kit(凭证 + 脚本骨架 + bootstrap,全 FC persona 一份)**:`$HOME/.clawd/deploy-kit/`(`scripts/` + `contract/bootstrap` + `.secrets/aliyun.env.local`)
|
|
10
10
|
- **persona 特化(本目录)**:`config.env`(注入值) + `contract/s.yaml.tmpl`(占位符清单) + `examples/`(默认 `nestjs-react`)
|
|
11
11
|
|
|
12
12
|
## 目录
|
|
@@ -14,7 +14,7 @@ FC 对应用只有一条要求:**一个监听 `$PORT` 的 HTTP server**。所以
|
|
|
14
14
|
```
|
|
15
15
|
# 共享 deploy-kit($HOME/.clawd/deploy-kit/,daemon 维护,全 persona 共用)
|
|
16
16
|
deploy-kit/
|
|
17
|
-
├── .secrets/aliyun.env
|
|
17
|
+
├── .secrets/aliyun.env.local 阿里云凭证(单源,使用者自己写;bundle 只带 *.example)
|
|
18
18
|
├── contract/bootstrap FC 启动入口(Node 参考实现:find node + cd + exec)
|
|
19
19
|
└── scripts/
|
|
20
20
|
├── new-extension.sh 从示例生成新 extension(纯 copy,daemon 自动跑)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# supabase 连接串的**唯一真源是 daemon
|
|
1
|
+
# supabase 连接串的**唯一真源是 daemon 的凭据表**(本机 `~/.clawd/secrets/supabase.env`,云上 gateway 经 env 注入)。
|
|
2
2
|
# 本文件是模板:scaffold(new-extension.sh)把下面的占位引用展开成同目录的 `.env` 给本地 dev 用;
|
|
3
3
|
# 线上那份由 publish.sh 渲进 s.yaml 的 environmentVariables。两条路取同一张表的同一个变量名,
|
|
4
4
|
# 所以不会出现「本地连一台、线上连另一台」的漂移(那会表现成 PGRST205 找不到表)。
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
FC 对应用只有一条要求:**一个监听 `$PORT` 的 HTTP server**。所以固化的是「发布管道」,不是技术栈。
|
|
8
8
|
|
|
9
|
-
- **共享 deploy-kit(凭证 + 脚本骨架 + bootstrap,全 FC persona 一份)**:`$HOME/.clawd/deploy-kit/`(`scripts/` + `contract/bootstrap` + `.secrets/aliyun.env`)
|
|
9
|
+
- **共享 deploy-kit(凭证 + 脚本骨架 + bootstrap,全 FC persona 一份)**:`$HOME/.clawd/deploy-kit/`(`scripts/` + `contract/bootstrap` + `.secrets/aliyun.env.local`)
|
|
10
10
|
- **persona 特化(本目录)**:`config.env`(dataclaw 注入值) + `contract/s.yaml.tmpl`(占位符清单) + `hooks/pre-deploy.sh`(发布前置) + `examples/`(默认 `nestjs-react`)
|
|
11
11
|
|
|
12
12
|
## 目录
|
|
@@ -14,7 +14,7 @@ FC 对应用只有一条要求:**一个监听 `$PORT` 的 HTTP server**。所以
|
|
|
14
14
|
```
|
|
15
15
|
# 共享 deploy-kit($HOME/.clawd/deploy-kit/,daemon 维护,全 persona 共用)
|
|
16
16
|
deploy-kit/
|
|
17
|
-
├── .secrets/aliyun.env
|
|
17
|
+
├── .secrets/aliyun.env.local 阿里云凭证(单源,使用者自己写;bundle 只带 *.example)
|
|
18
18
|
├── contract/bootstrap FC 启动入口(Node 参考实现:find node + cd + exec)
|
|
19
19
|
└── scripts/
|
|
20
20
|
├── new-extension.sh 从示例生成新 extension(纯 copy,daemon 自动跑)
|
package/dist/secrets/README.md
CHANGED
|
@@ -1,29 +1,47 @@
|
|
|
1
|
-
# `src/secrets/` ——
|
|
1
|
+
# `src/secrets/` —— 凭据表的 bundle 目录(只有占位模板,没有值)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
(`EnvironmentManifest.secrets[].name`)。daemon 在 spawn
|
|
3
|
+
每个 `<name>.env.example` 是一条**命名凭据**的占位模板,`name` 对齐环境清单
|
|
4
|
+
(`EnvironmentManifest.secrets[].name`)。daemon 在 spawn 时把凭据表合成一张
|
|
5
5
|
`Record<envName, value>`,只交给**真正用它的那个子进程**(MCP server / deploy-kit 发布脚本),
|
|
6
6
|
agent 主进程 env 一条都不放。读法与合并顺序见 `../deploy/secret-table.ts`。
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## 这里不放值:clawd 不随包 ship 任何凭据
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
本目录随 npm 包 / OTA 发给所有用户,**放进来的每一把 key 都等于公开**——不是比喻:
|
|
11
|
+
|
|
12
|
+
- deploy-kit 的阿里云 AK 曾以「共享 demo 凭证」身份放在 `deploy-kit/.secrets/aliyun.env`,随 npm 包发出去
|
|
13
|
+
**69 秒**就被 TruffleHog 收割、90 天内被 100+ 个境外 IP 验证约 600 次,最后主账号被阿里云风控锁
|
|
14
|
+
(`specs/2026-09-18-aliyun-ak-leak-rotate-design.md`)。
|
|
15
|
+
- 这里的 supabase 三件套(url / anon / **service-role**)曾经也是这么 ship 的。service-role 绕过 RLS,
|
|
16
|
+
等于整库管理员;而那台实例除 app-builder 的 demo 表外还承载 clawd 自己的 `clawd_prod` schema
|
|
17
|
+
(`persona_cloud_api_keys` / `device_bindings` / `lark_bot_bindings` 的明文 app_secret……)——
|
|
18
|
+
随包公开等于把中心库交出去(`specs/2026-09-18-supabase-key-leak-design.md`)。
|
|
19
|
+
|
|
20
|
+
所以 2026-09-18 起:`*.env` 不进 git(`clawd/.gitignore`),不进 dist(`scripts/copy-defaults.mjs`
|
|
21
|
+
平移时只放行 `*.example` 与本 README),desktop OTA 打的是 dist 所以同样没有。
|
|
13
22
|
|
|
14
|
-
|
|
15
|
-
- 「哪些 key 随 OTA 下发」在**目录层面就是可数的**——将来做收敛(见
|
|
16
|
-
`doc/glossary/persona-cloud.md` 的「随 OTA 下发的凭据 = 公开凭据」)时,要删的就是这个目录。
|
|
23
|
+
## 值从哪来
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
| 环境 | 来源 |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| 本机 | **`~/.clawd/secrets/<name>.env`**(凭据表覆盖目录,不随 OTA 覆盖)。照同名 `.example` 抄一份填值即可。改了下一个会话就生效,不用重启 daemon |
|
|
28
|
+
| 云上 | persona 仓库的 GitHub Secrets(同名)→ `register.mjs` → gateway 起 Pod 时经容器 env 交进来,走同一个交付点。**不读这两个目录** |
|
|
19
29
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
不在 M1b 范围。
|
|
30
|
+
本机什么都没配:凭据表为空,`persona/mcp-secret-render.ts` 会 warn 缺哪个变量名并渲成空串,MCP server
|
|
31
|
+
起不来时在会话里响亮报错;deploy-kit 的 `publish.sh` 对缺失占位符 fail-loud。**不会静默用错实例。**
|
|
23
32
|
|
|
24
|
-
|
|
33
|
+
开发者在 repo checkout 里跑 `tsx src/index.ts` 想图省事,也可以把真值放在本目录的 `<name>.env`——它是
|
|
34
|
+
gitignored 的,且 `pnpm build` 不会把它带进 dist。
|
|
35
|
+
|
|
36
|
+
## 为什么单独一个目录,而不是写在 persona bundle 里
|
|
37
|
+
|
|
38
|
+
原先 supabase 的 url / anon / service-role 是**明文 CLI 参数**硬写在
|
|
39
|
+
`persona-app-builder/.mcp.json` 里的。那个文件在 persona 目录下,agent 一个 `Read` 就看得见
|
|
40
|
+
——等于每次会话都把 key 摊给模型。挪到凭据表之后:
|
|
25
41
|
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
- persona 目录(agent 的 cwd 及其上级)里没有任何凭据值,只有 `${VAR}` 占位;
|
|
43
|
+
- 「消费方要哪些变量名」在**目录层面就是可数的**——就是这里的 `*.example`。
|
|
28
44
|
|
|
29
|
-
|
|
45
|
+
**不放 JWT 签发密钥**(`SUPABASE_AUTH_JWT_SECRET`):它能自签任意 role / 任意 user 的 token(含
|
|
46
|
+
`service_role`),交出去等于连「日后轮换 anon/service key」这个能力一起交出去;MCP server 里它唯一的用处是
|
|
47
|
+
`verify_jwt_secret` 自检。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# supabase 凭据(app-builder 系 persona 的 supabase MCP + deploy-kit 发布脚本用)。
|
|
2
|
+
#
|
|
3
|
+
# clawd 不随包 ship 任何一把 supabase key:把自己实例的值写进 **~/.clawd/secrets/supabase.env**
|
|
4
|
+
# (daemon 的凭据表覆盖目录,不随 OTA 覆盖,见 ../deploy/secret-table.ts)。这个目录里的 *.env
|
|
5
|
+
# 不进 git(clawd/.gitignore)、不进 dist(scripts/copy-defaults.mjs 只平移 *.example 与 README)。
|
|
6
|
+
# 云上不用文件:persona 仓库的 GitHub Secrets(同名四个)→ register.mjs → gateway 起 Pod 时经 env 注入。
|
|
7
|
+
#
|
|
8
|
+
# 四个名字都要给:前三个是 @aliyun-rds/supabase-mcp-server 的 commander option 默认值
|
|
9
|
+
# (process.env.SUPABASE_URL / SUPABASE_ANON_KEY / SUPABASE_SERVICE_ROLE_KEY);SUPABASE_KEY 是
|
|
10
|
+
# deploy-kit(s.yaml environmentVariables / 项目 server/.env)的历史名字,值同 anon。
|
|
11
|
+
#
|
|
12
|
+
# **不放 JWT 签发密钥**(SUPABASE_AUTH_JWT_SECRET):它能自签任意 role 的 token,MCP 里唯一用途是
|
|
13
|
+
# verify_jwt_secret 自检,摘掉零功能损失。
|
|
14
|
+
SUPABASE_URL=http://replace-me:80
|
|
15
|
+
SUPABASE_ANON_KEY=replace-me
|
|
16
|
+
SUPABASE_SERVICE_ROLE_KEY=replace-me
|
|
17
|
+
SUPABASE_KEY=replace-me
|
package/package.json
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
# 阿里云 RAM AccessKey — clawd ship 的共享 demo 凭证(publish.sh 先 source 这个)
|
|
2
|
-
# 归属 RAM 用户 clawd-fc-developer(独立收敛权限用户,跟 owner 主账号解耦)
|
|
3
|
-
# 每次 daemon 启动 refreshDeployKit 会用 defaults 里的最新版覆盖本文件(OTA 即升级)。
|
|
4
|
-
# 想用自己的 AK 覆盖:复制 aliyun.env.local.example → aliyun.env.local 并填自己的值。
|
|
5
|
-
# 需要权限:AliyunFCFullAccess + AliyunSTSAssumeRoleAccess
|
|
6
|
-
ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI5tAi7P7oySa3ohAzaYbj
|
|
7
|
-
ALIBABA_CLOUD_ACCESS_KEY_SECRET=NS470lOWTLeeAP9RUADXkpKNOrH5QX
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# supabase —— 阿里云托管 supabase 实例(公网 endpoint 121.196.249.178:80,
|
|
2
|
-
# 项目 ra-ae0i57kef06s6ix / clawd-app-builder,杭州可用区J)。
|
|
3
|
-
# 消费方两处,都经 daemon 的凭据表交付、都不落 persona 目录:
|
|
4
|
-
# - supabase MCP server(persona-app-builder/.mcp.json 的 ${...} 占位)
|
|
5
|
-
# —— @aliyun-rds/supabase-mcp-server 的 commander option 默认值就读这三个名字,
|
|
6
|
-
# 所以不再传 --supabase-* CLI 参数(参数会出现在 ps 输出里)。
|
|
7
|
-
# - deploy-kit 的 publish.sh / new-extension.sh(渲染进 s.yaml 的 environmentVariables
|
|
8
|
-
# 与项目 server/.env)—— 那两处历史上叫 SUPABASE_KEY,值同 anon。
|
|
9
|
-
#
|
|
10
|
-
# **不放 JWT 签发密钥**:它能自签任意 role / 任意 user 的 token(含 service_role),
|
|
11
|
-
# 下发出去等于把 anon/service key 的轮换能力一起交出去;而 MCP server 里它唯一的用处是
|
|
12
|
-
# verify_jwt_secret 这个自检工具报个 found/preview。摘掉零功能损失。
|
|
13
|
-
SUPABASE_URL=http://121.196.249.178:80
|
|
14
|
-
SUPABASE_ANON_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNzgzMzEwODU1LCJleHAiOjEzMjkzOTUwODU1fQ.sHLZH8q2SGWYbNPEFOzTFlQEtjVK3z1DlEqoU_5Uyyg
|
|
15
|
-
SUPABASE_SERVICE_ROLE_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJvbGUiOiJzZXJ2aWNlX3JvbGUiLCJpYXQiOjE3ODMzMTA4NTUsImV4cCI6MTMyOTM5NTA4NTV9.MdlymSh0DaJdiOVRmM3QnukUDtkOf_Eljh8_fpdLi8Q
|
|
16
|
-
SUPABASE_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJvbGUiOiJhbm9uIiwiaWF0IjoxNzgzMzEwODU1LCJleHAiOjEzMjkzOTUwODU1fQ.sHLZH8q2SGWYbNPEFOzTFlQEtjVK3z1DlEqoU_5Uyyg
|