fix(self-hosted): 身份改明碼 namespace(.env)+ path-based webhook trigger
壓測 §7.2:seed 通了但 creds push/push/runtime 全卡「缺少 api_key」——
self-hosted init 從不發 api_key,但三條路徑都建在多租戶 {api_key}:cred 模型上。
richblack 拍板:self-hosted 不需祕密 api_key,只需 namespace(分區標籤):
- config:ENV_MAP 加 NAMESPACE/ENCRYPTION_KEY + .env 自動載入(無 dotenv 依賴)
- namespace 明碼用戶自填(.env NAMESPACE=leo),沿用 api_key 路徑 → 零分叉
- encryption_key 用戶 .env 自填(工具不生成不 hash),須與 worker secret 一致
- creds/push/init:缺值改引導設 .env,不再叫去 register
- runtime:cypher 加 POST /webhooks/named/:ns/:name/trigger(namespace 走 path,
公開表單免 header);與 header 路徑共用 triggerNamed,不分叉
- push:self-hosted 顯示 path-based 公開 webhook URL
誠實限制:namespace 明碼非密碼;防外部呼叫靠 webhook 保護(mindset §6)。
CLI 1.3.0 → 1.3.1。SDD: self-hosted-init.md §7.7。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+27
-11
@@ -23,7 +23,13 @@ export async function cmdPush(filePath: string): Promise<void> {
|
||||
}
|
||||
|
||||
if (!config.api_key) {
|
||||
console.error(chalk.red('缺少 api_key,請重新執行 acr init。'));
|
||||
if (config.mode === 'self-hosted') {
|
||||
console.error(chalk.red('缺少 NAMESPACE(你的資料分區標籤)。'));
|
||||
console.log(chalk.gray('在專案 .env 設一行(明碼即可):'));
|
||||
console.log(chalk.cyan(' NAMESPACE=leo'));
|
||||
} else {
|
||||
console.error(chalk.red('缺少 api_key,請重新執行 acr init。'));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -126,17 +132,27 @@ export async function cmdPush(filePath: string): Promise<void> {
|
||||
const data = await res.json() as { name: string; webhook_url: string; created_at: string };
|
||||
deploySpinner.succeed(chalk.green(`✓ "${workflow.name}" 已部署`));
|
||||
|
||||
console.log(chalk.bold(`\n Webhook URL:${chalk.cyan(data.webhook_url)}`));
|
||||
console.log(chalk.gray(` 需帶 Header:X-Arcrun-API-Key: ${config.api_key.slice(0, 8)}...`));
|
||||
// self-hosted:namespace 明碼 → 給「namespace 進 path」的公開 URL(公開表單可直接打,免 header)。
|
||||
// standard:仍走 header(平台多租戶,api_key 是密碼不可進 path)。
|
||||
if (config.mode === 'self-hosted') {
|
||||
const pathUrl = `${executorUrl}/webhooks/named/${config.api_key}/${workflow.name}/trigger`;
|
||||
console.log(chalk.bold(`\n Webhook URL(公開可打,免 header):${chalk.cyan(pathUrl)}`));
|
||||
console.log(chalk.gray(' namespace 在 path 是明碼分區標籤(非密碼);要防外部濫用請對 webhook 加保護。'));
|
||||
console.log('');
|
||||
console.log(chalk.gray(' 公開表單 / curl 觸發:'));
|
||||
console.log(` ${chalk.cyan(`curl -X POST ${pathUrl} \\`)}`);
|
||||
console.log(` ${chalk.cyan(` -H 'Content-Type: application/json' -d '{"key": "value"}'`)}`);
|
||||
} else {
|
||||
console.log(chalk.bold(`\n Webhook URL:${chalk.cyan(data.webhook_url)}`));
|
||||
console.log(chalk.gray(` 需帶 Header:X-Arcrun-API-Key: ${config.api_key.slice(0, 8)}...`));
|
||||
console.log('');
|
||||
console.log(chalk.gray(' curl 觸發範例:'));
|
||||
console.log(` ${chalk.cyan(`curl -X POST ${data.webhook_url} \\`)}`);
|
||||
console.log(` ${chalk.cyan(` -H 'X-Arcrun-API-Key: ${config.api_key}' \\`)}`);
|
||||
console.log(` ${chalk.cyan(` -H 'Content-Type: application/json' -d '{"key": "value"}'`)}`);
|
||||
}
|
||||
console.log('');
|
||||
console.log(chalk.gray(' 測試執行:'));
|
||||
console.log(` ${chalk.cyan(`acr run ${workflow.name}`)}`);
|
||||
console.log('');
|
||||
console.log(chalk.gray(' curl 觸發範例:'));
|
||||
console.log(` ${chalk.cyan(`curl -X POST ${data.webhook_url} \\`)}`);
|
||||
console.log(` ${chalk.cyan(` -H 'X-Arcrun-API-Key: ${config.api_key}' \\`)}`);
|
||||
console.log(` ${chalk.cyan(` -H 'Content-Type: application/json' \\`)}`);
|
||||
console.log(` ${chalk.cyan(` -d '{"key": "value"}'`)}`);
|
||||
console.log(chalk.gray(' 測試執行:') + ` ${chalk.cyan(`acr run ${workflow.name}`)}`);
|
||||
console.log('');
|
||||
} catch (e) {
|
||||
deploySpinner.fail(chalk.red(`部署失敗:${e instanceof Error ? e.message : e}`));
|
||||
|
||||
Reference in New Issue
Block a user