@alipay/alipay-aipay 1.8.6 → 1.8.7
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/utils/jq.js +3 -1
- package/package.json +3 -3
- package/skill/VERSION +1 -1
- package/skill/references/normal/json/customer-messages.json +1 -1
- package/skill/references/normal/json/managed-jq-assets.json +1 -1
- package/skill/references/normal/json/policy-rules.json +1 -1
- package/skill/references/normal/scripts/managed_jq.mjs +1 -1
- package/skill/references/normal/scripts/render_customer_message.mjs +0 -1
- package/skill/references/normal/scripts/session_skill.mjs +3 -2
- package/skill/references/onboarding/modules/scripts/mcc.sh +19 -7
- package/skill-pre/VERSION +1 -1
- package/skill-pre/references/normal/json/customer-messages.json +1 -1
- package/skill-pre/references/normal/json/managed-jq-assets.json +1 -1
- package/skill-pre/references/normal/json/policy-rules.json +1 -1
- package/skill-pre/references/normal/scripts/managed_jq.mjs +1 -1
- package/skill-pre/references/normal/scripts/render_customer_message.mjs +0 -1
- package/skill-pre/references/normal/scripts/session_skill.mjs +3 -2
- package/skill-pre/references/normal/scripts/windows/policy.json +0 -1
- package/skill-pre/references/normal/scripts/windows/preflight.mjs +2 -2
- package/skill-pre/references/normal/scripts/windows/prepare.mjs +1 -1
- package/skill-pre/references/normal/scripts/windows/routing.mjs +2 -3
- package/skill-pre/references/normal/windows-environment.md +1 -1
- package/skill-pre/references/onboarding/modules/scripts/mcc.sh +19 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"rules":[{"policyId":"P-MCP-CONTRACT-FROZEN","scope":"all","severity":"critical","text":"只用当前 Skill 已验证的 MCP 脚本契约;禁止推断、改名或尝试近似方法。","runtimeText":"仅用已验证脚本;禁推断或尝试近似方法。"},{"policyId":"P-AUTH-BEFORE-ONBOARDING","scope":"onboarding","severity":"critical","text":"登录、scope 和 MCC 校验通过前,禁止 onboarding 查询或写入。","runtimeText":"登录/scope/MCC 未通过前禁查询和写入。"},{"policyId":"P-SIGNING-WRITE","scope":"onboarding.signing","severity":"critical","text":"签约材料校验通过后直接提交,不增加确认;缺失或非法时禁止提交。"},{"policyId":"P-SERVICE-WRITE","scope":"onboarding.service","severity":"critical","text":"服务创建摘要送达后直接创建;服务修改须取得绑定当前脱敏摘要的明确确认。"},{"policyId":"P-APPLICATION-WRITE","scope":"onboarding.application","severity":"critical","text":"完整新建材料或非空候选后的明确“新建”已构成创建确认;快照未变时不追加确认,公钥确认后直接提审。"},{"policyId":"P-WRITE-UNKNOWN","scope":"onboarding.write","severity":"critical","text":"非幂等写入结果不明时只读核验;仍无法确认则进入 UNKNOWN,禁止重试写入。"},{"policyId":"P-PARTIAL-RESULT","scope":"onboarding","severity":"critical","text":"签约、服务、应用分支独立记录,失败不回滚或覆盖其他成功结果。"},{"policyId":"P-MATERIAL-CATEGORY","scope":"onboarding.materials","severity":"required","text":"每轮只展示一个材料类别;同类一次收齐,已提供材料不得重复索取。"},{"policyId":"P-KEY-NO-PRIVATE","scope":"onboarding.application","severity":"critical","text":"Agent 禁止请求、读取、处理、保存或输出生产私钥,也不提供密钥生成命令;仅用户选择方案3后可打开本地静态页面,由用户在浏览器内自行生成并保存密钥,禁止 Agent 操作页面生成按钮或读取页面密钥。"},{"policyId":"P-KEY-PUBLIC-USER","scope":"onboarding.application","severity":"critical","text":"应用公钥只能由用户提供;缺少时禁止 createKeyConfirmPage,也不得补全、改写或添加 PEM 头尾。"},{"policyId":"P-AUTH-URL","scope":"onboarding.authorization","severity":"critical","text":"授权链接只由 auth.sh 构造并校验固定域名、路径和参数;禁用 verification_url。"},{"policyId":"P-KEY-URL","scope":"onboarding.application","severity":"critical","text":"公钥确认只展示 createKeyConfirmPage 返回并校验的裸 URL;禁止二维码链接和 alipays://。"},{"policyId":"P-AUTH-URL-AUTO-OPEN","scope":"onboarding.authorization","severity":"critical","text":"授权 URL 交付后调用受控 opener;失败时保留同一裸 URL 和复制兜底。"},{"policyId":"P-KEY-URL-AUTO-OPEN","scope":"onboarding.application","severity":"critical","text":"公钥 URL 交付后调用受控 opener;失败时保留同一裸 URL 和复制兜底。"},{"policyId":"P-KEY-TOOL-DOWNLOAD","scope":"onboarding.application","severity":"critical","text":"预发版查询应用列表成功后展示三种公钥获取方式,不自动下载密钥工具。用户明确选择方案3才打开随包本地离线页面;失败引导自行下载安装官方密钥工具。页面由用户自行生成、保存密钥,Agent 只接收用户提供的公钥。"},{"policyId":"P-A2M-SANDBOX","scope":"integration.aipay","severity":"critical","text":"AI 按量付费沙箱 serviceId 固定为 api_mock_service_id,SDK 使用沙箱网关;生产网关和真实 serviceId 只用于正式配置。","runtimeText":"A2M 沙箱固定 api_mock_service_id 与沙箱网关;生产值仅用于正式配置。"},{"policyId":"P-A2M-SUCCESS","scope":"integration.aipay","severity":"critical","text":"自动联调只有在 HTTP 200、非空可归属资源、无明确业务失败且适用 Payment-Validation 有效时通过。","runtimeText":"联调仅在 HTTP 200、资源可归属、无业务失败且适用回执有效时通过。"},{"policyId":"P-SANDBOX-CREDENTIAL-EXCEPTION","scope":"integration.sandbox","severity":"critical","text":"Unix/macOS/Linux 与 Windows READY 只允许快速沙箱实际返回且已校验的买家登录/支付密码在登记的沙箱摘要和付款体验中经 stdin 临时渲染。Windows READY 的快速沙箱配置须写入当前项目受保护的本机文件;Windows LEGACY/CODE_ONLY 手工沙箱允许用户在 sandbox.windows.manual_setup 后提供当前沙箱应用的 APPID、支付宝公钥、应用公钥、与当前开发语言匹配的应用私钥和沙箱账号信息;Agent 只能将其用于已确认目标项目的受保护配置,不得在普通日志或业务状态中复述或另存原文;除 AI 网页应用收款的登记沙箱摘要及最终三项买家配置外,不得在回复或摘要中复述原文。两类例外均不得扩展到生产环境账号、应用私钥或密码。 最终收口仅 AI 网页应用收款可从当前会话已校验且已交付的登记摘要展示沙箱买家测试账号、登录密码和支付密码三项,密码明文展示(含 Windows);按量付费及 APP 支付不展示最终沙箱配置区块;不得扩展到其他凭据、原始配置或生产信息。","runtimeText":"Unix/macOS/Linux 与 Windows READY 已校验快速沙箱买家密码按既有登记摘要/付款体验展示;Windows LEGACY/CODE_ONLY 手工资料用于受保护项目,仅网页收款登记摘要可明文展示买家密码;最终收口仅网页收款三项买家信息;其他原文禁复述、另存或扩展到生产值。"},{"policyId":"P-SENSITIVE-STATE","scope":"all","severity":"critical","text":"用户公钥仅用于当前 app key/verify-key/verify-key-and-audit 调用,禁止在回复、摘要、普通日志、跨会话状态或宽权限临时文件中复述或保存;除登记的沙箱例外外,私钥、token、Payment-Proof、签名串、完整支付表单和未脱敏响应同样不得进入这些位置;临时 URL 仅可由登记动作校验后在该动作正文展示。","runtimeText":"公钥限当前 app 调用且禁复述/保存;敏感值禁入回复/摘要/日志/状态/宽权限文件;临时 URL 仅由登记动作展示。"},{"policyId":"P-PROJECT-PROTECT","scope":"integration","severity":"critical","text":"不得清空、覆盖或删除用户既有项目;只在已确认目标路径和范围内做必要修改。","runtimeText":"禁清空/覆盖/删除既有项目;仅改已确认路径和范围。"},{"policyId":"P-CUSTOMER-OUTPUT-EXCLUSIVE","scope":"all","severity":"critical","text":"登记 runner/script 的 stdout 是唯一对客正文,禁止增删改写;阻塞消息送达后立即等待用户。","runtimeText":"登记 stdout 原文是唯一正文;阻塞送达后立即等待。"},{"policyId":"P-ONBOARDING-CONTROL-CHANNEL","scope":"onboarding","severity":"critical","text":"剔除 ALIPAY_AIPAY_INTERNAL 内部行后再处理 stdout;内部行禁止对客,正文为空时直接转移。","runtimeText":"内部行禁对客;正文为空按唯一终态转移。"},{"policyId":"P-AUTH-PAGE-DELIVERY-BARRIER","scope":"onboarding.authorization","severity":"critical","text":"`auth.page` stdout 必须先独立送达,再 opener 和有限轮询;不得合并 pending 或收口,也不等待确认。"},{"policyId":"P-KEY-PAGE-DELIVERY-BARRIER","scope":"onboarding.application","severity":"critical","text":"`application.key.page` stdout 必须先独立送达,再 opener 和有限轮询;不得合并 pending 或收口,也不等待确认。"},{"policyId":"P-DETERMINISTIC-HANDOFF","scope":"all","severity":"critical","text":"只执行 flow 动作处登记命令并按唯一终态立即转移;禁止追加命令重复解析,失败只走登记恢复。","runtimeText":"仅执行登记命令并按唯一终态转移;禁追加解析;失败只走登记恢复。"}],"officialUrls":{"aipaySite":"https://aipay.alipay.com/","aipaySkillSite":"https://aipay.alipay.com/?from=alipay-aipay-skill","merchantPlatform":"https://b.alipay.com/page/portal/home","openPlatform":"https://open.alipay.com/","openPlatformHome":"https://open.alipay.com","technicalSupport":"https://opensupport.alipay.com/support/intelligent-services?form=payskill","keyToolManual":"https://opendocs.alipay.com/isv/02kipk","keyToolMac":"https://ideservice.alipay.com/ide/getPluginUrl.htm?clientType=assistant&platform=mac&channelType=WEB","keyToolWindows":"https://ideservice.alipay.com/ide/getPluginUrl.htm?clientType=assistant&platform=win&channelType=WEB","androidSandboxAlipay":"https://mdn.alipayobjects.com/sandboxsys/afts/img/_itHRrdOD9oAAAAAAAAAAAAADgSLAQBr/original","sandboxToolFallback":"https://open.alipay.com/develop/sandbox/tool","sandboxGateway":"https://openapi-sandbox.dl.alipaydev.com/gateway.do","productionGateway":"https://openapi.alipay.com/gateway.do","openPlatformPaySkill":"https://open.alipay.com?form=payskill","traditionalPaymentSkill":"https://github.com/alipay/ai/tree/main/skills","dingtalkSupportGroupQr":"https://mdn.alipayobjects.com/huamei_5fajmi/afts/img/MlFpRKmYyLIAAAAARJAAAAgADlahAQFr/original","wecomCommunityGroupQr":"https://mdn.alipayobjects.com/huamei_5fajmi/afts/img/Cz0TTZVO7_4AAAAAQDAAAAgADlahAQFr/fmt.webp","applicationKeyFormat":"https://opendocs.alipay.com/common/055l5k"},"authorizationProducts":[{"productName":"AI 按量付费","salesCode":"I1080300001000160457","scope":"app:all,machine_pay:write,agmnt:write"},{"productName":"AI 网页应用收款","salesCode":"I1080300001000041203","scope":"app:all,fast_instant_trade_pay:write"},{"productName":"AI 移动应用收款","salesCode":"I1080300001000041313","scope":"app:all,auth_alipay_apppay:write"}],"temporaryUrlAllowlist":{"authorization":{"host":"aipay.alipay.com","path":"/cli-auth","requiredQueryParams":["deviceCode","productCode","mccCode"],"optionalQueryParams":["platform"]},"publicKeyConfirmation":[{"host":"aipay.alipay.com","path":"/public-key-confirm","requiredQueryParams":["keyConfirmToken"],"optionalQueryParams":[]},{"host":"open.alipay.com","path":"/ai/ai-resource-center/public-key-confirm","requiredQueryParams":["keyConfirmToken"],"optionalQueryParams":[]}],"windowsOnboardingRedirect":{"host":"aipay.alipay.com","path":"/","requiredQueryParams":["from","reason","platform_id"],"optionalQueryParams":[]}}}
|
|
@@ -19,7 +19,7 @@ const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:JQ_PREPARE=';
|
|
|
19
19
|
function readManifest() {
|
|
20
20
|
const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
21
21
|
if (
|
|
22
|
-
parsed
|
|
22
|
+
!parsed ||
|
|
23
23
|
!/^\d+\.\d+\.\d+$/u.test(parsed.version || '') ||
|
|
24
24
|
!Number.isInteger(parsed.downloadTimeoutMs) || parsed.downloadTimeoutMs <= 0 ||
|
|
25
25
|
!Number.isInteger(parsed.idleTimeoutMs) || parsed.idleTimeoutMs <= 0 ||
|
|
@@ -63,6 +63,7 @@ export function createSessionSkill({sourceDir, channel, version, packageVersion,
|
|
|
63
63
|
fs.writeFileSync(path.join(skillDir,'PROFILE'),selectedProfile,{flag:'wx',mode:0o600});
|
|
64
64
|
}
|
|
65
65
|
const manifest = filesUnder(skillDir);
|
|
66
|
+
// Older updaters verify this handoff before they can load the new Skill.
|
|
66
67
|
const receipt = {schemaVersion:1, scope:'session', channel, version, packageVersion,
|
|
67
68
|
skillDir:fs.realpathSync(skillDir), targetDir:path.resolve(targetDir)};
|
|
68
69
|
fs.writeFileSync(path.join(skillDir,receiptName),JSON.stringify({...receipt,manifest}),{flag:'wx',mode:0o600});
|
|
@@ -84,7 +85,7 @@ function readProfile(skillDir) {
|
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
export function verifySessionSkill(receipt, {home = os.homedir(), channel, version, packageVersion, targetDir} = {}) {
|
|
87
|
-
if (!receipt || receipt.
|
|
88
|
+
if (!receipt || receipt.scope!=='session' || !['stable','pre'].includes(receipt.channel) || !semver.test(receipt.version||'') || !path.isAbsolute(receipt.skillDir||'') ||
|
|
88
89
|
!path.isAbsolute(receipt.targetDir||'') || !semver.test(receipt.packageVersion||'')) throw Error('Invalid session receipt');
|
|
89
90
|
const root=sessionSkillRoot(home), dir=receipt.skillDir;
|
|
90
91
|
plain(path.dirname(root),true); plain(root,true); plain(dir,true);
|
|
@@ -95,7 +96,7 @@ export function verifySessionSkill(receipt, {home = os.homedir(), channel, versi
|
|
|
95
96
|
}
|
|
96
97
|
plain(path.join(dir,receiptName));
|
|
97
98
|
const saved=JSON.parse(fs.readFileSync(path.join(dir,receiptName),'utf8'));
|
|
98
|
-
for (const key of ['
|
|
99
|
+
for (const key of ['scope','channel','version','packageVersion','skillDir','targetDir']) {
|
|
99
100
|
if (saved[key]!==receipt[key]) throw Error('Session receipt mismatch');
|
|
100
101
|
}
|
|
101
102
|
identity(dir,receipt.channel,receipt.version);
|
|
@@ -190,7 +190,7 @@ export function resultError(error) {
|
|
|
190
190
|
reason==='USER_SCOPE_REQUIRED'?'USE_NON_ELEVATED_SESSION':
|
|
191
191
|
['STORAGE_FAILED','ENVIRONMENT_BUSY','ENVIRONMENT_STATE_INVALID'].includes(reason)?'REPAIR_LOCAL_ENVIRONMENT_THEN_RECHECK':
|
|
192
192
|
'INSPECT_FAILURE_THEN_RECHECK';
|
|
193
|
-
return {
|
|
193
|
+
return {status:needsSetup?'NEEDS_SETUP':'BLOCKED',reason,dependency:error.dependency||'',recovery,validationCoverage:'NOT_VERIFIED'};
|
|
194
194
|
}
|
|
195
195
|
export function report(error) {
|
|
196
196
|
const r=resultError(error);
|
|
@@ -207,6 +207,6 @@ if(process.argv[1]&&path.resolve(process.argv[1])===fileURLToPath(import.meta.ur
|
|
|
207
207
|
const v=k==='PATH'?c.env[k].split(';').map(p=>slash(p).replace(/^([a-zA-Z]):/,(_,d)=>'/'+d.toLowerCase())).join(':'):c.env[k];
|
|
208
208
|
console.log('export '+k+'='+quote(v));
|
|
209
209
|
}
|
|
210
|
-
} else console.error('ALIPAY_AIPAY_INTERNAL:WINDOWS_ENV_RESULT='+JSON.stringify({
|
|
210
|
+
} else console.error('ALIPAY_AIPAY_INTERNAL:WINDOWS_ENV_RESULT='+JSON.stringify({status:'READY',validationCoverage:'NOT_VERIFIED'}));
|
|
211
211
|
}catch(e){report(e);process.exitCode=78;}
|
|
212
212
|
}
|
|
@@ -147,7 +147,7 @@ export function runEnvironment(args) {
|
|
|
147
147
|
else fail('ENVIRONMENT_ARGUMENT_INVALID');
|
|
148
148
|
console.log('CLI_ENV:READY');
|
|
149
149
|
if (recovering) process.stderr.write('ALIPAY_AIPAY_INTERNAL:WINDOWS_ROUTE=' +
|
|
150
|
-
JSON.stringify({
|
|
150
|
+
JSON.stringify({rootIntent:options['--root-intent'],route:'READY'}) + '\n');
|
|
151
151
|
return 0;
|
|
152
152
|
}catch(e){report(e);return 78;}
|
|
153
153
|
}
|
|
@@ -43,9 +43,8 @@ export function selectRoute({rootIntent = '', authorized = false, repair = false
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function emit(result) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return value;
|
|
46
|
+
process.stderr.write(prefix + 'WINDOWS_ROUTE=' + JSON.stringify(result) + '\n');
|
|
47
|
+
return result;
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
export function runWindowsEntry(args) {
|
|
@@ -16,7 +16,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" windows-entry --root-in
|
|
|
16
16
|
|
|
17
17
|
用户明确要求安装并通过 Skill 完成签约/开通或完整接入时附加 `--prepare-authorized true`;仅代码开发且没有依赖准备授权时先只读检查。用户明确选择站点时附加 `--site-selected true`。准备授权只覆盖用户级依赖,不包含登录、签约或应用写入。
|
|
18
18
|
|
|
19
|
-
退出 0 只表示分流完成。必须取得唯一 `ALIPAY_AIPAY_INTERNAL:WINDOWS_ROUTE=<JSON
|
|
19
|
+
退出 0 只表示分流完成。必须取得唯一 `ALIPAY_AIPAY_INTERNAL:WINDOWS_ROUTE=<JSON>`,校验结果为 JSON 对象、rootIntent 等于当前根意图、route 为 READY、BLOCKED、LEGACY 或 CODE_ONLY;非零、超时、缺失或冲突均按 BLOCKED 停止。READY 才执行本地快速沙箱和签约;BLOCKED 说明内部 `WINDOWS_ENV_RESULT` 的实际 reason/dependency 及恢复动作,等待环境修复,不能输出站点引导;LEGACY 仅用于不支持的执行映射或用户明确选择站点。后续 Windows runtime 命令附加当前 `--windows-route`;BLOCKED 不进入 bootstrap、业务 flow 或项目写入。CODE_ONLY 只放行独立代码开发,根意图和诊断原因沿用本次入口事实。修复可选工具后重新只读复检,取得唯一 READY 才恢复快速沙箱和开通动作。环境故障不关闭遥测,也不改变 SESSION_ID、run_id、计数或会话采集选择。
|
|
20
20
|
|
|
21
21
|
`integration_only/full_process` 遇到已识别的 Git Bash、jq、CLI 或安装辅助工具缺失/运行失败,以及这些工具的有限安装、下载、哈希/签名校验或预算耗尽失败时,返回 `CODE_ONLY`。失败工具不得继续执行,校验失败的安装包不得运行。以唯一 WINDOWS_ROUTE 的 route 决定是否进入开发;WINDOWS_ENV_RESULT 的失败诊断保留实际原因,不能将其误读为业务能力可用。该分流沿用 Integration 的原生 Node 路径,沙箱默认 `VERIFY_PENDING`,跳过快速沙箱;用户主动提供完整有效手工资料并写入、校验项目配置后,可记沙箱 `READY`,无需先将环境分流恢复为 READY。各测试按自身实际依赖执行:缺失工具所依赖的动作仍不能运行;原生 Python 402 联调不依赖 Git Bash,但仍须 Python、curl、服务可访问、沙箱配置等前置就绪。最终如实列出未完成项,不自动引导站点开通。完整接入在代码部分检查后停在 Onboarding 前,待工具恢复且复检 READY 才恢复。Node 版本不足、实际存储故障、状态损坏、回滚失败或未知错误仍为 BLOCKED;项目路径和生产配置保护要求不变。下文“失败保持 BLOCKED”对上述可选工具例外按 CODE_ONLY 处理。
|
|
22
22
|
|
|
@@ -174,7 +174,7 @@ read_mcc_tree_cache() {
|
|
|
174
174
|
--arg salesCode "$sales_code" \
|
|
175
175
|
--argjson now "$now" \
|
|
176
176
|
--argjson ttl "$ttl" '
|
|
177
|
-
if
|
|
177
|
+
if type == "object"
|
|
178
178
|
and .productType == $productType
|
|
179
179
|
and .salesCode == $salesCode
|
|
180
180
|
and ((.createdAtEpoch // null) | type == "number")
|
|
@@ -201,7 +201,6 @@ write_mcc_tree_cache() {
|
|
|
201
201
|
--argjson createdAtEpoch "$now" \
|
|
202
202
|
--argjson tree "$tree" \
|
|
203
203
|
'{
|
|
204
|
-
schemaVersion: 1,
|
|
205
204
|
productType: $productType,
|
|
206
205
|
salesCode: $salesCode,
|
|
207
206
|
createdAtEpoch: $createdAtEpoch,
|
|
@@ -229,7 +228,7 @@ read_mcc_selection_cache() {
|
|
|
229
228
|
--arg receipt "$receipt" \
|
|
230
229
|
--argjson now "$now" \
|
|
231
230
|
--argjson ttl "$ttl" '
|
|
232
|
-
if
|
|
231
|
+
if type == "object"
|
|
233
232
|
and .productType == $productType
|
|
234
233
|
and .salesCode == $salesCode
|
|
235
234
|
and .query == $query
|
|
@@ -283,7 +282,6 @@ write_mcc_selection_cache() {
|
|
|
283
282
|
--argjson candidateRows "$candidate_rows" \
|
|
284
283
|
--argjson details "$details" \
|
|
285
284
|
'{
|
|
286
|
-
schemaVersion: 4,
|
|
287
285
|
productType: $productType,
|
|
288
286
|
salesCode: $salesCode,
|
|
289
287
|
query: $query,
|
|
@@ -358,7 +356,14 @@ claim_mcc_agent_phase() {
|
|
|
358
356
|
--arg inputId "$input_id" \
|
|
359
357
|
--arg phase "$phase" \
|
|
360
358
|
--arg catalogDigest "$catalog_digest" '
|
|
361
|
-
if
|
|
359
|
+
if type != "object" or ((.entries // null) | type != "array")
|
|
360
|
+
or any(.entries[];
|
|
361
|
+
type != "object" or (.query | type) != "string"
|
|
362
|
+
or (.inputId | type) != "string" or .inputId == ""
|
|
363
|
+
or (.phase != "review" and .phase != "repair" and .phase != "result")
|
|
364
|
+
or (.catalogDigest | type) != "string"
|
|
365
|
+
or (.catalogDigest | test("^[0-9a-f]{64}$") | not)
|
|
366
|
+
) then
|
|
362
367
|
error("invalid MCC agent review state")
|
|
363
368
|
elif $phase == "review" and any(.entries[]; .inputId == $inputId) then
|
|
364
369
|
error("MCC agent review already started")
|
|
@@ -383,7 +388,7 @@ claim_mcc_agent_phase() {
|
|
|
383
388
|
--arg inputId "$input_id" \
|
|
384
389
|
--arg phase "$phase" \
|
|
385
390
|
--arg catalogDigest "$catalog_digest" \
|
|
386
|
-
'{
|
|
391
|
+
'{entries: [{query: $query, inputId: $inputId, phase: $phase, catalogDigest: $catalogDigest}]}' \
|
|
387
392
|
>"$tmp" 2>/dev/null; then
|
|
388
393
|
rm -f "$tmp" 2>/dev/null || true
|
|
389
394
|
rmdir "$lock" 2>/dev/null || true
|
|
@@ -430,7 +435,14 @@ bind_mcc_agent_result() {
|
|
|
430
435
|
--arg inputId "$input_id" \
|
|
431
436
|
--arg catalogDigest "$catalog_digest" \
|
|
432
437
|
--argjson candidateCodes "$candidate_codes" '
|
|
433
|
-
if
|
|
438
|
+
if type != "object" or ((.entries // null) | type != "array")
|
|
439
|
+
or any(.entries[];
|
|
440
|
+
type != "object" or (.query | type) != "string"
|
|
441
|
+
or (.inputId | type) != "string" or .inputId == ""
|
|
442
|
+
or (.phase != "review" and .phase != "repair" and .phase != "result")
|
|
443
|
+
or (.catalogDigest | type) != "string"
|
|
444
|
+
or (.catalogDigest | test("^[0-9a-f]{64}$") | not)
|
|
445
|
+
) then
|
|
434
446
|
error("invalid MCC agent review state")
|
|
435
447
|
elif (any(.entries[];
|
|
436
448
|
.query == $query and .inputId == $inputId and .phase == "review" and .catalogDigest == $catalogDigest
|