scene-capability-engine 3.0.8 → 3.2.0
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/CHANGELOG.md +55 -0
- package/docs/331-poc-adaptation-roadmap.md +21 -2
- package/docs/331-poc-dual-track-integration-guide.md +10 -6
- package/docs/331-poc-weekly-delivery-checklist.md +5 -0
- package/docs/README.md +6 -0
- package/docs/command-reference.md +262 -4
- package/docs/handoff-profile-integration-guide.md +88 -0
- package/docs/interactive-customization/331-poc-sce-integration-checklist.md +148 -0
- package/docs/interactive-customization/README.md +362 -0
- package/docs/interactive-customization/adapter-extension-contract.md +55 -0
- package/docs/interactive-customization/adapter-extension-contract.sample.json +59 -0
- package/docs/interactive-customization/adapter-extension-contract.schema.json +192 -0
- package/docs/interactive-customization/approval-role-policy-baseline.json +36 -0
- package/docs/interactive-customization/change-intent.schema.json +72 -0
- package/docs/interactive-customization/change-plan.sample.json +41 -0
- package/docs/interactive-customization/change-plan.schema.json +125 -0
- package/docs/interactive-customization/cross-industry-replication-guide.md +49 -0
- package/docs/interactive-customization/dialogue-governance-policy-baseline.json +49 -0
- package/docs/interactive-customization/domain-pack-extension-flow.md +71 -0
- package/docs/interactive-customization/execution-record.schema.json +62 -0
- package/docs/interactive-customization/governance-alert-playbook.md +51 -0
- package/docs/interactive-customization/governance-report-template.md +46 -0
- package/docs/interactive-customization/governance-threshold-baseline.json +14 -0
- package/docs/interactive-customization/guardrail-policy-baseline.json +27 -0
- package/docs/interactive-customization/high-risk-action-catalog.json +22 -0
- package/docs/interactive-customization/moqui-adapter-interface.md +40 -0
- package/docs/interactive-customization/moqui-context-provider.sample.json +72 -0
- package/docs/interactive-customization/moqui-copilot-context-contract.json +50 -0
- package/docs/interactive-customization/moqui-copilot-integration-guide.md +100 -0
- package/docs/interactive-customization/moqui-interactive-template-playbook.md +94 -0
- package/docs/interactive-customization/non-technical-usability-report.md +57 -0
- package/docs/interactive-customization/page-context.sample.json +73 -0
- package/docs/interactive-customization/page-context.schema.json +150 -0
- package/docs/interactive-customization/phase-acceptance-evidence.md +110 -0
- package/docs/interactive-customization/runtime-mode-policy-baseline.json +99 -0
- package/docs/moqui-template-core-library-playbook.md +28 -0
- package/docs/release-checklist.md +29 -4
- package/docs/security-governance-default-baseline.md +54 -0
- package/docs/starter-kit/README.md +50 -0
- package/docs/starter-kit/handoff-manifest.starter.json +32 -0
- package/docs/starter-kit/handoff-profile-ci.sample.yml +53 -0
- package/docs/starter-kit/release.workflow.sample.yml +41 -0
- package/docs/zh/README.md +12 -0
- package/lib/auto/moqui-recovery-sequence.js +62 -0
- package/lib/commands/auto.js +245 -34
- package/lib/commands/scene.js +867 -0
- package/lib/data/moqui-capability-lexicon.json +14 -1
- package/lib/interactive-customization/change-plan-gate-core.js +201 -0
- package/lib/interactive-customization/index.js +9 -0
- package/lib/interactive-customization/moqui-interactive-adapter.js +732 -0
- package/package.json +27 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2026.02.
|
|
2
|
+
"version": "2026.02.19.2",
|
|
3
3
|
"source": "sce-moqui-core",
|
|
4
4
|
"capabilities": [
|
|
5
5
|
{
|
|
@@ -244,6 +244,19 @@
|
|
|
244
244
|
"workflow-approval-center"
|
|
245
245
|
]
|
|
246
246
|
},
|
|
247
|
+
{
|
|
248
|
+
"canonical": "platform-interactive-customization-loop",
|
|
249
|
+
"aliases": [
|
|
250
|
+
"interactive-customization-loop",
|
|
251
|
+
"interactive-change-loop",
|
|
252
|
+
"moqui-interactive-customization-loop",
|
|
253
|
+
"scene.moqui.interactive.customization.loop",
|
|
254
|
+
"scene-moqui-interactive-customization-loop"
|
|
255
|
+
],
|
|
256
|
+
"deprecated_aliases": [
|
|
257
|
+
"interactive-customization-pipeline"
|
|
258
|
+
]
|
|
259
|
+
},
|
|
247
260
|
{
|
|
248
261
|
"canonical": "platform-reporting-audit-ops",
|
|
249
262
|
"aliases": [
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_POLICY = 'docs/interactive-customization/guardrail-policy-baseline.json';
|
|
4
|
+
const DEFAULT_CATALOG = 'docs/interactive-customization/high-risk-action-catalog.json';
|
|
5
|
+
|
|
6
|
+
function toUniqueList(value) {
|
|
7
|
+
if (!Array.isArray(value)) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
return Array.from(new Set(
|
|
11
|
+
value
|
|
12
|
+
.map(item => `${item || ''}`.trim())
|
|
13
|
+
.filter(Boolean)
|
|
14
|
+
));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function normalizeRiskLevel(value) {
|
|
18
|
+
const risk = `${value || ''}`.trim().toLowerCase();
|
|
19
|
+
return ['low', 'medium', 'high'].includes(risk) ? risk : null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function buildCheck(id, passed, severity, details) {
|
|
23
|
+
return {
|
|
24
|
+
id,
|
|
25
|
+
passed: passed === true,
|
|
26
|
+
severity,
|
|
27
|
+
details: details || null
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function evaluatePlanGate(plan, policy, catalog) {
|
|
32
|
+
const checks = [];
|
|
33
|
+
const actions = Array.isArray(plan && plan.actions) ? plan.actions.filter(item => item && typeof item === 'object') : [];
|
|
34
|
+
const riskLevel = normalizeRiskLevel(plan && plan.risk_level);
|
|
35
|
+
const approval = plan && plan.approval && typeof plan.approval === 'object' ? plan.approval : {};
|
|
36
|
+
const security = plan && plan.security && typeof plan.security === 'object' ? plan.security : {};
|
|
37
|
+
|
|
38
|
+
const planShapePassed = (
|
|
39
|
+
Boolean(plan && typeof plan.plan_id === 'string' && plan.plan_id.trim().length > 0) &&
|
|
40
|
+
Boolean(plan && typeof plan.intent_id === 'string' && plan.intent_id.trim().length > 0) &&
|
|
41
|
+
Boolean(riskLevel) &&
|
|
42
|
+
actions.length > 0
|
|
43
|
+
);
|
|
44
|
+
checks.push(buildCheck(
|
|
45
|
+
'plan-shape',
|
|
46
|
+
planShapePassed,
|
|
47
|
+
'deny',
|
|
48
|
+
planShapePassed ? null : 'plan_id/intent_id/risk_level/actions is invalid or missing'
|
|
49
|
+
));
|
|
50
|
+
|
|
51
|
+
const policyApproval = policy && policy.approval_policy && typeof policy.approval_policy === 'object'
|
|
52
|
+
? policy.approval_policy
|
|
53
|
+
: {};
|
|
54
|
+
const policySecurity = policy && policy.security_policy && typeof policy.security_policy === 'object'
|
|
55
|
+
? policy.security_policy
|
|
56
|
+
: {};
|
|
57
|
+
const catalogData = catalog && catalog.catalog && typeof catalog.catalog === 'object'
|
|
58
|
+
? catalog.catalog
|
|
59
|
+
: {};
|
|
60
|
+
|
|
61
|
+
const denyActionTypes = new Set(toUniqueList(catalogData.deny_action_types));
|
|
62
|
+
const reviewActionTypes = new Set(toUniqueList(catalogData.review_required_action_types));
|
|
63
|
+
|
|
64
|
+
const deniedActionHits = actions
|
|
65
|
+
.map(item => `${item.type || ''}`.trim())
|
|
66
|
+
.filter(type => type && denyActionTypes.has(type));
|
|
67
|
+
checks.push(buildCheck(
|
|
68
|
+
'deny-action-types',
|
|
69
|
+
deniedActionHits.length === 0,
|
|
70
|
+
'deny',
|
|
71
|
+
deniedActionHits.length > 0
|
|
72
|
+
? `blocked action types: ${Array.from(new Set(deniedActionHits)).join(', ')}`
|
|
73
|
+
: null
|
|
74
|
+
));
|
|
75
|
+
|
|
76
|
+
const reviewActionHits = actions
|
|
77
|
+
.map(item => `${item.type || ''}`.trim())
|
|
78
|
+
.filter(type => type && reviewActionTypes.has(type));
|
|
79
|
+
const reviewActionApproved = reviewActionHits.length === 0 || approval.status === 'approved';
|
|
80
|
+
checks.push(buildCheck(
|
|
81
|
+
'review-action-types',
|
|
82
|
+
reviewActionApproved,
|
|
83
|
+
'review',
|
|
84
|
+
reviewActionApproved
|
|
85
|
+
? null
|
|
86
|
+
: `review-required action types without approval: ${Array.from(new Set(reviewActionHits)).join(', ')}`
|
|
87
|
+
));
|
|
88
|
+
|
|
89
|
+
const approvalRiskLevels = new Set(
|
|
90
|
+
toUniqueList(policyApproval.require_approval_for_risk_levels).map(item => item.toLowerCase())
|
|
91
|
+
);
|
|
92
|
+
const riskApprovalPassed = !approvalRiskLevels.has(riskLevel || '') || approval.status === 'approved';
|
|
93
|
+
checks.push(buildCheck(
|
|
94
|
+
'risk-approval',
|
|
95
|
+
riskApprovalPassed,
|
|
96
|
+
'review',
|
|
97
|
+
riskApprovalPassed
|
|
98
|
+
? null
|
|
99
|
+
: `risk level ${riskLevel} requires approval`
|
|
100
|
+
));
|
|
101
|
+
|
|
102
|
+
const maxActionsWithoutApproval = Number(policyApproval.max_actions_without_approval);
|
|
103
|
+
const actionCountApprovalPassed = (
|
|
104
|
+
!Number.isFinite(maxActionsWithoutApproval) ||
|
|
105
|
+
maxActionsWithoutApproval < 0 ||
|
|
106
|
+
actions.length <= maxActionsWithoutApproval ||
|
|
107
|
+
approval.status === 'approved'
|
|
108
|
+
);
|
|
109
|
+
checks.push(buildCheck(
|
|
110
|
+
'action-count-approval',
|
|
111
|
+
actionCountApprovalPassed,
|
|
112
|
+
'review',
|
|
113
|
+
actionCountApprovalPassed
|
|
114
|
+
? null
|
|
115
|
+
: `action count ${actions.length} exceeds max_actions_without_approval ${maxActionsWithoutApproval}`
|
|
116
|
+
));
|
|
117
|
+
|
|
118
|
+
const privilegeEscalation = actions.some(item => item && item.requires_privilege_escalation === true);
|
|
119
|
+
const requireDualApproval = policyApproval.require_dual_approval_for_privilege_escalation === true;
|
|
120
|
+
const dualApprovalPassed = !privilegeEscalation || !requireDualApproval || approval.dual_approved === true;
|
|
121
|
+
checks.push(buildCheck(
|
|
122
|
+
'privilege-escalation-dual-approval',
|
|
123
|
+
dualApprovalPassed,
|
|
124
|
+
'review',
|
|
125
|
+
dualApprovalPassed
|
|
126
|
+
? null
|
|
127
|
+
: 'privilege escalation detected without dual approval'
|
|
128
|
+
));
|
|
129
|
+
|
|
130
|
+
const touchesSensitiveData = actions.some(item => item && item.touches_sensitive_data === true);
|
|
131
|
+
const requireMasking = policySecurity.require_masking_when_sensitive_data === true;
|
|
132
|
+
const maskingPassed = !touchesSensitiveData || !requireMasking || security.masking_applied === true;
|
|
133
|
+
checks.push(buildCheck(
|
|
134
|
+
'sensitive-data-masking',
|
|
135
|
+
maskingPassed,
|
|
136
|
+
'deny',
|
|
137
|
+
maskingPassed
|
|
138
|
+
? null
|
|
139
|
+
: 'sensitive data change requires masking_applied=true'
|
|
140
|
+
));
|
|
141
|
+
|
|
142
|
+
const forbidPlaintextSecrets = policySecurity.forbid_plaintext_secrets === true;
|
|
143
|
+
const plaintextSecretsPassed = !forbidPlaintextSecrets || security.plaintext_secrets_in_payload !== true;
|
|
144
|
+
checks.push(buildCheck(
|
|
145
|
+
'plaintext-secrets',
|
|
146
|
+
plaintextSecretsPassed,
|
|
147
|
+
'deny',
|
|
148
|
+
plaintextSecretsPassed
|
|
149
|
+
? null
|
|
150
|
+
: 'plaintext secrets detected in plan payload'
|
|
151
|
+
));
|
|
152
|
+
|
|
153
|
+
const hasIrreversibleAction = actions.some(item => item && item.irreversible === true);
|
|
154
|
+
const requireBackup = policySecurity.require_backup_for_irreversible_actions === true;
|
|
155
|
+
const backupPassed = !hasIrreversibleAction || !requireBackup || Boolean(`${security.backup_reference || ''}`.trim());
|
|
156
|
+
checks.push(buildCheck(
|
|
157
|
+
'irreversible-backup',
|
|
158
|
+
backupPassed,
|
|
159
|
+
'deny',
|
|
160
|
+
backupPassed
|
|
161
|
+
? null
|
|
162
|
+
: 'irreversible actions require backup_reference'
|
|
163
|
+
));
|
|
164
|
+
|
|
165
|
+
const failedDenyChecks = checks.filter(item => item.passed !== true && item.severity === 'deny');
|
|
166
|
+
const failedReviewChecks = checks.filter(item => item.passed !== true && item.severity === 'review');
|
|
167
|
+
|
|
168
|
+
let decision = 'allow';
|
|
169
|
+
if (failedDenyChecks.length > 0) {
|
|
170
|
+
decision = 'deny';
|
|
171
|
+
} else if (failedReviewChecks.length > 0) {
|
|
172
|
+
decision = 'review-required';
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
decision,
|
|
177
|
+
checks,
|
|
178
|
+
failed_deny_checks: failedDenyChecks.map(item => item.id),
|
|
179
|
+
failed_review_checks: failedReviewChecks.map(item => item.id),
|
|
180
|
+
reasons: checks
|
|
181
|
+
.filter(item => item.passed !== true && item.details)
|
|
182
|
+
.map(item => item.details),
|
|
183
|
+
summary: {
|
|
184
|
+
check_total: checks.length,
|
|
185
|
+
failed_total: checks.filter(item => item.passed !== true).length,
|
|
186
|
+
failed_deny_total: failedDenyChecks.length,
|
|
187
|
+
failed_review_total: failedReviewChecks.length,
|
|
188
|
+
action_count: actions.length,
|
|
189
|
+
risk_level: riskLevel
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module.exports = {
|
|
195
|
+
DEFAULT_POLICY,
|
|
196
|
+
DEFAULT_CATALOG,
|
|
197
|
+
toUniqueList,
|
|
198
|
+
normalizeRiskLevel,
|
|
199
|
+
buildCheck,
|
|
200
|
+
evaluatePlanGate
|
|
201
|
+
};
|