@enterpriseai/cli 3.19.2 → 3.19.4
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/README.md +28 -0
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +116 -35
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/eai-managed-deploy-customer-source.d.ts.map +1 -1
- package/dist/commands/eai-managed-deploy-customer-source.js +24 -0
- package/dist/commands/eai-managed-deploy-customer-source.js.map +1 -1
- package/dist/commands/eai-managed-deploy-github-dispatch.d.ts.map +1 -1
- package/dist/commands/eai-managed-deploy-github-dispatch.js +30 -0
- package/dist/commands/eai-managed-deploy-github-dispatch.js.map +1 -1
- package/dist/commands/eai-managed-source-move.js +2 -2
- package/dist/commands/eai-managed-source-move.js.map +1 -1
- package/dist/commands/env.js +15 -2
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/gofer.js +8 -1
- package/dist/commands/gofer.js.map +1 -1
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +187 -8
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +6 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/provision.d.ts.map +1 -1
- package/dist/commands/provision.js +27 -13
- package/dist/commands/provision.js.map +1 -1
- package/dist/commands/publicapi.d.ts.map +1 -1
- package/dist/commands/publicapi.js +14 -2
- package/dist/commands/publicapi.js.map +1 -1
- package/dist/commands/resources.d.ts.map +1 -1
- package/dist/commands/resources.js +41 -20
- package/dist/commands/resources.js.map +1 -1
- package/dist/commands/support.d.ts +18 -0
- package/dist/commands/support.d.ts.map +1 -0
- package/dist/commands/support.js +110 -0
- package/dist/commands/support.js.map +1 -0
- package/dist/commands/tenant.js +39 -3
- package/dist/commands/tenant.js.map +1 -1
- package/dist/commands/types.d.ts +12 -1
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js +172 -35
- package/dist/commands/types.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +89 -44
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/vertical.d.ts.map +1 -1
- package/dist/commands/vertical.js +163 -15
- package/dist/commands/vertical.js.map +1 -1
- package/dist/index.js +54 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-guide.d.ts.map +1 -1
- package/dist/lib/agent-guide.js +25 -4
- package/dist/lib/agent-guide.js.map +1 -1
- package/dist/lib/api.d.ts +25 -4
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +152 -39
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/cloud-env.d.ts +1 -0
- package/dist/lib/cloud-env.d.ts.map +1 -1
- package/dist/lib/cloud-env.js +28 -15
- package/dist/lib/cloud-env.js.map +1 -1
- package/dist/lib/config.d.ts +6 -2
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +13 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/eai-managed-deploy-contract.d.ts +4 -0
- package/dist/lib/eai-managed-deploy-contract.d.ts.map +1 -1
- package/dist/lib/eai-managed-deploy-contract.js.map +1 -1
- package/dist/lib/eai-managed-deploy-operation.d.ts.map +1 -1
- package/dist/lib/eai-managed-deploy-operation.js +14 -0
- package/dist/lib/eai-managed-deploy-operation.js.map +1 -1
- package/dist/lib/eai-managed-deploy-state.d.ts.map +1 -1
- package/dist/lib/eai-managed-deploy-state.js +15 -1
- package/dist/lib/eai-managed-deploy-state.js.map +1 -1
- package/dist/lib/eai-managed-source-client-types.d.ts +3 -0
- package/dist/lib/eai-managed-source-client-types.d.ts.map +1 -1
- package/dist/lib/error-codes.d.ts.map +1 -1
- package/dist/lib/error-codes.js +6 -3
- package/dist/lib/error-codes.js.map +1 -1
- package/dist/lib/object-type-export-filesystem.d.ts +13 -0
- package/dist/lib/object-type-export-filesystem.d.ts.map +1 -0
- package/dist/lib/object-type-export-filesystem.js +112 -0
- package/dist/lib/object-type-export-filesystem.js.map +1 -0
- package/dist/lib/object-type-export.d.ts +13 -0
- package/dist/lib/object-type-export.d.ts.map +1 -0
- package/dist/lib/object-type-export.js +173 -0
- package/dist/lib/object-type-export.js.map +1 -0
- package/dist/lib/output.d.ts +1 -0
- package/dist/lib/output.d.ts.map +1 -1
- package/dist/lib/output.js +24 -1
- package/dist/lib/output.js.map +1 -1
- package/dist/lib/platform-diagnostics.d.ts +21 -0
- package/dist/lib/platform-diagnostics.d.ts.map +1 -0
- package/dist/lib/platform-diagnostics.js +50 -0
- package/dist/lib/platform-diagnostics.js.map +1 -0
- package/dist/lib/profile.d.ts +9 -2
- package/dist/lib/profile.d.ts.map +1 -1
- package/dist/lib/profile.js +139 -4
- package/dist/lib/profile.js.map +1 -1
- package/dist/lib/schema-builder.d.ts +2 -0
- package/dist/lib/schema-builder.d.ts.map +1 -1
- package/dist/lib/schema-builder.js +5 -0
- package/dist/lib/schema-builder.js.map +1 -1
- package/dist/lib/support-context.d.ts +31 -0
- package/dist/lib/support-context.d.ts.map +1 -0
- package/dist/lib/support-context.js +193 -0
- package/dist/lib/support-context.js.map +1 -0
- package/dist/lib/support-redaction.d.ts +10 -0
- package/dist/lib/support-redaction.d.ts.map +1 -0
- package/dist/lib/support-redaction.js +44 -0
- package/dist/lib/support-redaction.js.map +1 -0
- package/dist/lib/support-report.d.ts +68 -0
- package/dist/lib/support-report.d.ts.map +1 -0
- package/dist/lib/support-report.js +165 -0
- package/dist/lib/support-report.js.map +1 -0
- package/package.json +3 -2
- package/resources/deploy/eai-app-template/.github/workflows/eai-app.yml +46 -13
- package/resources/deploy/eai-app-template/producer-pin.json +8 -8
- package/resources/deploy/eai-app-template/scripts/source-unknown-deployment-evidence.mjs +29 -2
- package/resources/deploy/eai-app-template/tests/source-unknown-deployment-evidence.test.mjs +99 -1
- package/resources/gofer/agents-skills/eai/SKILL.md +20 -0
- package/resources/gofer/claude-commands/eai.md +20 -0
- package/resources/gofer/claude-skills/eai/SKILL.md +20 -0
- package/resources/gofer/commands/0_gofer_start.md +18 -0
- package/resources/gofer/commands/gofer_eai_first_run.md +18 -0
- package/resources/gofer/copilot-prompts/eai.prompt.md +20 -0
- package/resources/gofer/gemini/commands/gofer/eai.md +20 -0
- package/resources/gofer/github-skills/eai/SKILL.md +20 -0
- package/resources/gofer/grok-skills/eai/SKILL.md +20 -0
- package/resources/gofer/instruction-templates/base/agents-base.md +18 -0
- package/resources/gofer/instruction-templates/base/claude-base.md +18 -0
- package/resources/gofer/instruction-templates/base/copilot-base.md +18 -0
- package/resources/gofer/instruction-templates/gofer/gofer-claude.md +4 -0
- package/resources/gofer/node-scripts/generate-commands.mjs +26 -0
- package/resources/gofer/references/platform/eai-support.md +19 -0
- package/resources/gofer/specify-commands/0_gofer_start.md +18 -0
- package/resources/gofer/specify-commands/gofer_eai_first_run.md +18 -0
- package/resources/gofer/system-skills/eai/SKILL.md +20 -0
- package/resources/linked-sources.json +2 -2
|
@@ -234,6 +234,7 @@ jobs:
|
|
|
234
234
|
--target-tenant-id "$TARGET_TENANT_ID" \
|
|
235
235
|
--operation-id "$OPERATION_ID" \
|
|
236
236
|
--nonce "$NONCE" \
|
|
237
|
+
--ref "$GITHUB_REF" \
|
|
237
238
|
--expected-config-hash "$CONFIG_HASH" \
|
|
238
239
|
--environment "$DEPLOY_ENVIRONMENT" \
|
|
239
240
|
--preferred-environment "$PREFERRED_DEPLOY_ENVIRONMENT" \
|
|
@@ -450,7 +451,7 @@ jobs:
|
|
|
450
451
|
shell: bash
|
|
451
452
|
run: |
|
|
452
453
|
if [[ "$LOCAL_E2E_TUNNEL" == true ]]; then
|
|
453
|
-
[[ "$SOURCE_MODE" == eai-cli-generated && "$GITHUB_EVENT_NAME" == workflow_dispatch && "$REUSABLE_CALL" != true ]]
|
|
454
|
+
[[ ( "$SOURCE_MODE" == eai-cli-generated || "$SOURCE_MODE" == source-unknown ) && "$GITHUB_EVENT_NAME" == workflow_dispatch && "$REUSABLE_CALL" != true ]]
|
|
454
455
|
[[ "$DEPLOY_ENVIRONMENT" == dev || "$DEPLOY_ENVIRONMENT" == preview ]]
|
|
455
456
|
[[ "$EAI_BOUND_PUBLIC_API_URL" =~ ^https://[a-z0-9-]+-8000\.[a-z0-9-]+\.devtunnels\.ms$ ]]
|
|
456
457
|
else
|
|
@@ -795,14 +796,33 @@ jobs:
|
|
|
795
796
|
const local = evidence.localE2e;
|
|
796
797
|
const repositoryId = process.env.GITHUB_REPOSITORY_ID;
|
|
797
798
|
const expiresAt = process.env.LOCAL_E2E_EXPIRES_AT;
|
|
798
|
-
|
|
799
|
-
|
|
799
|
+
const sourceUnknownLocal = process.env.SOURCE_MODE === 'source-unknown';
|
|
800
|
+
const expectedKeys = sourceUnknownLocal
|
|
801
|
+
? 'audience,expiresAt,mode,nonceDigest,origin'
|
|
802
|
+
: 'audience,expiresAt,mode,origin,templateCommitSha';
|
|
803
|
+
if (!local || Object.keys(local).sort().join(',') !== expectedKeys ||
|
|
804
|
+
local.mode !== (sourceUnknownLocal ? 'source-unknown-local-v1' : 'local-tunnel-v1') ||
|
|
805
|
+
local.origin !== process.env.EAI_BOUND_PUBLIC_API_URL ||
|
|
800
806
|
local.expiresAt !== expiresAt || !/^[1-9][0-9]*$/.test(repositoryId) ||
|
|
801
|
-
|
|
807
|
+
Date.parse(expiresAt) <= Date.now()) {
|
|
802
808
|
throw new Error('Build evidence local endpoint binding changed.');
|
|
803
809
|
}
|
|
804
|
-
|
|
805
|
-
|
|
810
|
+
if (sourceUnknownLocal && local.nonceDigest !== 'sha256:' + createHash('sha256').update(evidence.nonce).digest('hex')) {
|
|
811
|
+
throw new Error('Build evidence local nonce binding changed.');
|
|
812
|
+
}
|
|
813
|
+
if (!sourceUnknownLocal && !/^[a-f0-9]{40}$/.test(local.templateCommitSha)) {
|
|
814
|
+
throw new Error('Build evidence local template binding changed.');
|
|
815
|
+
}
|
|
816
|
+
const tuple = sourceUnknownLocal
|
|
817
|
+
? ['eai.source-unknown-local-e2e-aud.v1', local.origin, process.env.TENANT_ID,
|
|
818
|
+
process.env.TARGET_TENANT_ID || process.env.TENANT_ID, process.env.APP_KEY, evidence.operationId,
|
|
819
|
+
repositoryId, evidence.workflowPath, evidence.ref, evidence.commitSha,
|
|
820
|
+
evidence.configHash, local.nonceDigest, expiresAt]
|
|
821
|
+
: ['eai.cli-managed-local-e2e-aud.v1', local.origin, evidence.operationId, repositoryId, local.templateCommitSha, expiresAt];
|
|
822
|
+
const prefix = sourceUnknownLocal
|
|
823
|
+
? 'api://enterprise-ai-publicapi/source-unknown/local-v1/'
|
|
824
|
+
: 'api://enterprise-ai-publicapi/eai-cli-generated/local-v1/';
|
|
825
|
+
const audience = prefix + createHash('sha256').update(JSON.stringify(tuple)).digest('hex');
|
|
806
826
|
if (local.audience !== audience) throw new Error('Build evidence local OIDC audience changed.');
|
|
807
827
|
} else if (evidence.localE2e !== undefined) {
|
|
808
828
|
throw new Error('Unexpected local endpoint binding in build evidence.');
|
|
@@ -1016,7 +1036,7 @@ jobs:
|
|
|
1016
1036
|
set -euo pipefail
|
|
1017
1037
|
validate_endpoint_and_audience() {
|
|
1018
1038
|
if [[ "$LOCAL_E2E_TUNNEL" == true ]]; then
|
|
1019
|
-
[[ "$SOURCE_MODE" == eai-cli-generated && "$GITHUB_EVENT_NAME" == workflow_dispatch && "$REUSABLE_CALL" != true ]]
|
|
1039
|
+
[[ ( "$SOURCE_MODE" == eai-cli-generated || "$SOURCE_MODE" == source-unknown ) && "$GITHUB_EVENT_NAME" == workflow_dispatch && "$REUSABLE_CALL" != true ]]
|
|
1020
1040
|
[[ "$DEPLOY_ENVIRONMENT" == dev || "$DEPLOY_ENVIRONMENT" == preview ]]
|
|
1021
1041
|
[[ "$EAI_BOUND_PUBLIC_API_URL" =~ ^https://[a-z0-9-]+-8000\.[a-z0-9-]+\.devtunnels\.ms$ ]]
|
|
1022
1042
|
node - <<'NODE'
|
|
@@ -1032,14 +1052,27 @@ jobs:
|
|
|
1032
1052
|
const local = evidence.localE2e;
|
|
1033
1053
|
const repoId = process.env.GITHUB_REPOSITORY_ID;
|
|
1034
1054
|
const expiry = process.env.LOCAL_E2E_EXPIRES_AT;
|
|
1035
|
-
|
|
1036
|
-
|
|
1055
|
+
const sourceUnknownLocal = process.env.SOURCE_MODE === 'source-unknown';
|
|
1056
|
+
const expectedKeys = sourceUnknownLocal
|
|
1057
|
+
? 'audience,expiresAt,mode,nonceDigest,origin'
|
|
1058
|
+
: 'audience,expiresAt,mode,origin,templateCommitSha';
|
|
1059
|
+
if (!local || Object.keys(local).sort().join(',') !== expectedKeys ||
|
|
1060
|
+
local.mode !== (sourceUnknownLocal ? 'source-unknown-local-v1' : 'local-tunnel-v1') ||
|
|
1061
|
+
local.origin !== process.env.EAI_BOUND_PUBLIC_API_URL ||
|
|
1037
1062
|
local.expiresAt !== expiry || !/^[1-9][0-9]*$/.test(repoId) ||
|
|
1038
|
-
!/^cli-managed-[a-f0-9]{32}$/.test(evidence.operationId) ||
|
|
1039
|
-
!/^[a-f0-9]{40}$/.test(local.templateCommitSha) ||
|
|
1040
1063
|
!Number.isFinite(Date.parse(expiry)) || Date.parse(expiry) <= Date.now()) process.exit(1);
|
|
1041
|
-
const tuple =
|
|
1042
|
-
|
|
1064
|
+
const tuple = sourceUnknownLocal
|
|
1065
|
+
? ['eai.source-unknown-local-e2e-aud.v1', local.origin, process.env.TENANT_ID,
|
|
1066
|
+
evidence.targetTenantId || process.env.TENANT_ID, process.env.APP_KEY, evidence.operationId, repoId,
|
|
1067
|
+
evidence.workflowPath, evidence.ref, evidence.commitSha, evidence.configHash,
|
|
1068
|
+
local.nonceDigest, expiry]
|
|
1069
|
+
: ['eai.cli-managed-local-e2e-aud.v1', local.origin, evidence.operationId, repoId, local.templateCommitSha, expiry];
|
|
1070
|
+
if (sourceUnknownLocal ? local.nonceDigest !== 'sha256:' + createHash('sha256').update(evidence.nonce).digest('hex')
|
|
1071
|
+
: !/^[a-f0-9]{40}$/.test(local.templateCommitSha)) process.exit(1);
|
|
1072
|
+
const prefix = sourceUnknownLocal
|
|
1073
|
+
? 'api://enterprise-ai-publicapi/source-unknown/local-v1/'
|
|
1074
|
+
: 'api://enterprise-ai-publicapi/eai-cli-generated/local-v1/';
|
|
1075
|
+
const audience = prefix + createHash('sha256').update(JSON.stringify(tuple)).digest('hex');
|
|
1043
1076
|
if (local.audience !== audience) process.exit(1);
|
|
1044
1077
|
process.stdout.write(audience);
|
|
1045
1078
|
NODE
|
|
@@ -2,28 +2,28 @@
|
|
|
2
2
|
"schemaVersion": "eai.managed-deploy-producer-pin.v1",
|
|
3
3
|
"repository": "eai-support/eai-app-template",
|
|
4
4
|
"candidate": {
|
|
5
|
-
"commit": "
|
|
5
|
+
"commit": "623c4430ba017b8da5b36e84e2fcafd819f79169",
|
|
6
6
|
"workflow": {
|
|
7
7
|
"path": ".github/workflows/eai-app.yml",
|
|
8
|
-
"sha256": "sha256:
|
|
8
|
+
"sha256": "sha256:bce4e34fe5c47377e6a679966a37257d944cd00ccf3c15b4ba437f144ed559ed"
|
|
9
9
|
},
|
|
10
10
|
"collector": {
|
|
11
11
|
"path": "scripts/source-unknown-deployment-evidence.mjs",
|
|
12
|
-
"sha256": "sha256:
|
|
12
|
+
"sha256": "sha256:06e7f33bf1db1d7adbebb75a76d2756e46371318f36d2518c5cfbb58ad4f5e1c"
|
|
13
13
|
},
|
|
14
14
|
"evidenceTest": {
|
|
15
15
|
"path": "tests/source-unknown-deployment-evidence.test.mjs",
|
|
16
|
-
"sha256": "sha256:
|
|
16
|
+
"sha256": "sha256:fe5f8381d882ac39656b67b30e1e18193cb676a8aba26a6776a88880a3bb5827"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"releaseGate": {
|
|
20
20
|
"status": "released",
|
|
21
|
-
"tag": "v1.0.
|
|
22
|
-
"commit": "
|
|
21
|
+
"tag": "v1.0.13",
|
|
22
|
+
"commit": "623c4430ba017b8da5b36e84e2fcafd819f79169"
|
|
23
23
|
},
|
|
24
24
|
"githubProducerIdentity": {
|
|
25
25
|
"profile": "github-environment-v1",
|
|
26
|
-
"templateCommitSha": "
|
|
27
|
-
"workflowSha256": "sha256:
|
|
26
|
+
"templateCommitSha": "623c4430ba017b8da5b36e84e2fcafd819f79169",
|
|
27
|
+
"workflowSha256": "sha256:bce4e34fe5c47377e6a679966a37257d944cd00ccf3c15b4ba437f144ed559ed"
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -181,7 +181,7 @@ function localE2eBinding(options, mode, environment, root) {
|
|
|
181
181
|
const operationId = option(options, 'operationId');
|
|
182
182
|
const repositoryId = option(options, 'repositoryId');
|
|
183
183
|
if (
|
|
184
|
-
|
|
184
|
+
!['eai-cli-generated', 'source-unknown'].includes(mode) ||
|
|
185
185
|
!['preview', 'dev'].includes(environment) ||
|
|
186
186
|
option(options, 'githubEventName') !== 'workflow_dispatch' ||
|
|
187
187
|
option(options, 'reusableCall') === 'true' ||
|
|
@@ -189,7 +189,6 @@ function localE2eBinding(options, mode, environment, root) {
|
|
|
189
189
|
!/^[1-9][0-9]*$/.test(repositoryId) ||
|
|
190
190
|
!Number.isSafeInteger(Number(repositoryId)) ||
|
|
191
191
|
String(Number(repositoryId)) !== repositoryId ||
|
|
192
|
-
!/^cli-managed-[a-f0-9]{32}$/.test(operationId) ||
|
|
193
192
|
!/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?\+00:00$/.test(expiresAt) ||
|
|
194
193
|
!Number.isFinite(Date.parse(expiresAt)) ||
|
|
195
194
|
Date.parse(expiresAt) <= Date.now() ||
|
|
@@ -197,6 +196,34 @@ function localE2eBinding(options, mode, environment, root) {
|
|
|
197
196
|
) {
|
|
198
197
|
throw new Error('Local deployment requires an exact direct DEV/preview tunnel binding.');
|
|
199
198
|
}
|
|
199
|
+
if (mode === 'source-unknown') {
|
|
200
|
+
const nonce = option(options, 'nonce');
|
|
201
|
+
const tenantId = option(options, 'tenantId');
|
|
202
|
+
const targetTenant = option(options, 'targetTenantId') || tenantId;
|
|
203
|
+
const appKey = option(options, 'appKey');
|
|
204
|
+
const workflowPath = option(options, 'workflow', '.github/workflows/eai-app.yml');
|
|
205
|
+
const ref = option(options, 'ref', process.env.GITHUB_REF || '');
|
|
206
|
+
const commitSha = option(options, 'commit', process.env.GITHUB_SHA || '');
|
|
207
|
+
const configHash = option(options, 'expectedConfigHash');
|
|
208
|
+
if (!/^source-unknown-[a-f0-9]{16}$/.test(operationId)
|
|
209
|
+
|| !tenantId || !targetTenant || !appKey || !nonce
|
|
210
|
+
|| workflowPath !== CANONICAL_WORKFLOW_PATH
|
|
211
|
+
|| !/^refs\/heads\//.test(ref)
|
|
212
|
+
|| !/^[a-f0-9]{40}$/.test(commitSha)
|
|
213
|
+
|| !SHA256_DIGEST.test(configHash)) {
|
|
214
|
+
throw new Error('Local source-unknown operation binding is incomplete.');
|
|
215
|
+
}
|
|
216
|
+
const nonceDigest = `sha256:${createHash('sha256').update(nonce).digest('hex')}`;
|
|
217
|
+
const fields = ['eai.source-unknown-local-e2e-aud.v1', origin, tenantId,
|
|
218
|
+
targetTenant, appKey, operationId, repositoryId, workflowPath, ref,
|
|
219
|
+
commitSha, configHash, nonceDigest, expiresAt];
|
|
220
|
+
return { mode: 'source-unknown-local-v1', origin, expiresAt, nonceDigest,
|
|
221
|
+
audience: 'api://enterprise-ai-publicapi/source-unknown/local-v1/'
|
|
222
|
+
+ createHash('sha256').update(JSON.stringify(fields)).digest('hex') };
|
|
223
|
+
}
|
|
224
|
+
if (!/^cli-managed-[a-f0-9]{32}$/.test(operationId)) {
|
|
225
|
+
throw new Error('Local CLI operation binding is invalid.');
|
|
226
|
+
}
|
|
200
227
|
const binding = JSON.parse(readRegularFileNoFollow(root, '.eai/cli-managed-source-operation.json').toString('utf8'));
|
|
201
228
|
if (
|
|
202
229
|
binding.schemaVersion !== 'eai.cli_managed_source_operation.v1' ||
|
|
@@ -25,12 +25,13 @@ import { tmpdir } from 'node:os';
|
|
|
25
25
|
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
26
26
|
import { fileURLToPath } from 'node:url';
|
|
27
27
|
import test from 'node:test';
|
|
28
|
+
import { runInNewContext } from 'node:vm';
|
|
28
29
|
import { gunzipSync } from 'node:zlib';
|
|
29
30
|
|
|
30
31
|
const canonicalWorkflowRelativePath = '.github/workflows/eai-app.yml';
|
|
31
32
|
const fixtureDirectory = 'tests/fixtures/source-unknown';
|
|
32
33
|
const canonicalDigest =
|
|
33
|
-
'
|
|
34
|
+
'bce4e34fe5c47377e6a679966a37257d944cd00ccf3c15b4ba437f144ed559ed';
|
|
34
35
|
const generatedDigest =
|
|
35
36
|
'77d4951b3e6852ead73cef8b9e8901e3de774f9aca70f71cc0c932c13903ff32';
|
|
36
37
|
const digest = (bytes) => createHash('sha256').update(bytes).digest('hex');
|
|
@@ -1747,6 +1748,103 @@ test('local CLI dispatch binds direct DEV tunnel, original template and numeric
|
|
|
1747
1748
|
}
|
|
1748
1749
|
});
|
|
1749
1750
|
|
|
1751
|
+
test('local customer-owned source uses its own exact direct-operation audience', () => {
|
|
1752
|
+
const root = mkdtempSync(join(tmpdir(), 'eai-source-unknown-local-dispatch-'));
|
|
1753
|
+
try {
|
|
1754
|
+
writeFixtureApp(root);
|
|
1755
|
+
execFileSync('git', ['init', '-q'], { cwd: root });
|
|
1756
|
+
execFileSync('git', ['-c', 'user.name=Fixture', '-c', 'user.email=fixture@example.com',
|
|
1757
|
+
'commit', '--allow-empty', '-m', 'fixture'], { cwd: root });
|
|
1758
|
+
const commit = execFileSync('git', ['rev-parse', 'HEAD'], { cwd: root, encoding: 'utf8' }).trim();
|
|
1759
|
+
const expiry = new Date(Date.now() + 30 * 60 * 1000).toISOString().replace('Z', '+00:00');
|
|
1760
|
+
const args = ['validate-dispatch', '--root', root, '--source-mode', 'source-unknown',
|
|
1761
|
+
'--app-key', 'rates-review', '--tenant-id', 'tenant-parent',
|
|
1762
|
+
'--target-tenant-id', 'hosting-tenant', '--operation-id', `source-unknown-${'a'.repeat(16)}`,
|
|
1763
|
+
'--nonce', 'one-time-source-nonce', '--ref', 'refs/heads/main',
|
|
1764
|
+
'--environment', 'dev', '--expected-config-hash', configHash(root),
|
|
1765
|
+
'--commit', commit, '--workflow-sha', commit,
|
|
1766
|
+
'--public-api-url', 'https://careful-8000.eai.devtunnels.ms',
|
|
1767
|
+
'--local-e2e-tunnel', 'true', '--local-e2e-expires-at', expiry,
|
|
1768
|
+
'--github-event-name', 'workflow_dispatch', '--reusable-call', 'false',
|
|
1769
|
+
'--repository-id', '12345'];
|
|
1770
|
+
runEvidenceScript(args);
|
|
1771
|
+
const withoutTarget = [...args];
|
|
1772
|
+
withoutTarget.splice(withoutTarget.indexOf('--target-tenant-id'), 2);
|
|
1773
|
+
runEvidenceScript(withoutTarget);
|
|
1774
|
+
for (const [key, value] of [
|
|
1775
|
+
['--public-api-url', 'https://attacker.example'],
|
|
1776
|
+
['--operation-id', `cli-managed-${'a'.repeat(32)}`],
|
|
1777
|
+
['--ref', 'refs/pull/1/merge'],
|
|
1778
|
+
['--environment', 'prod'],
|
|
1779
|
+
['--local-e2e-expires-at', '2000-01-01T00:00:00+00:00'],
|
|
1780
|
+
['--repository-id', '0'],
|
|
1781
|
+
['--reusable-call', 'true'],
|
|
1782
|
+
]) {
|
|
1783
|
+
const mutated = [...args];
|
|
1784
|
+
mutated[mutated.indexOf(key) + 1] = value;
|
|
1785
|
+
const result = spawnSync(process.execPath, [evidenceScript, ...mutated], { encoding: 'utf8' });
|
|
1786
|
+
assert.equal(result.status, 1, `${key}=${value} must fail`);
|
|
1787
|
+
}
|
|
1788
|
+
} finally {
|
|
1789
|
+
rmSync(root, { recursive: true, force: true });
|
|
1790
|
+
}
|
|
1791
|
+
});
|
|
1792
|
+
|
|
1793
|
+
test('direct local workflow checks the same audience with explicit and omitted target tenants', () => {
|
|
1794
|
+
const workflow = readFileSync(workflowPath, 'utf8');
|
|
1795
|
+
const marker = 'const tuple = sourceUnknownLocal';
|
|
1796
|
+
const first = workflow.indexOf(marker);
|
|
1797
|
+
const second = workflow.indexOf(marker, first + marker.length);
|
|
1798
|
+
assert.ok(first >= 0 && second > first);
|
|
1799
|
+
const snippets = [first, second].map((start) => {
|
|
1800
|
+
const end = workflow.indexOf('if (local.audience !== audience)', start);
|
|
1801
|
+
assert.ok(end > start);
|
|
1802
|
+
return `${workflow.slice(start, end)}\naudience;`;
|
|
1803
|
+
});
|
|
1804
|
+
const origin = 'https://careful-8000.eai.devtunnels.ms';
|
|
1805
|
+
const tenantId = 'tenant-parent';
|
|
1806
|
+
const nonce = 'one-time-source-nonce';
|
|
1807
|
+
const nonceDigest = `sha256:${digest(nonce)}`;
|
|
1808
|
+
const expiry = '2026-10-11T02:00:00+00:00';
|
|
1809
|
+
const evidence = {
|
|
1810
|
+
nonce,
|
|
1811
|
+
operationId: `source-unknown-${'a'.repeat(16)}`,
|
|
1812
|
+
workflowPath: canonicalWorkflowRelativePath,
|
|
1813
|
+
ref: 'refs/heads/main',
|
|
1814
|
+
commitSha: 'b'.repeat(40),
|
|
1815
|
+
configHash: `sha256:${'c'.repeat(64)}`,
|
|
1816
|
+
};
|
|
1817
|
+
const audienceFor = (snippet, targetInput, evidenceTarget) =>
|
|
1818
|
+
runInNewContext(snippet, {
|
|
1819
|
+
createHash,
|
|
1820
|
+
process: { env: {
|
|
1821
|
+
TENANT_ID: tenantId,
|
|
1822
|
+
TARGET_TENANT_ID: targetInput,
|
|
1823
|
+
APP_KEY: 'rates-review',
|
|
1824
|
+
}, exit: () => { throw new Error('Unexpected workflow rejection.'); } },
|
|
1825
|
+
sourceUnknownLocal: true,
|
|
1826
|
+
local: { origin, nonceDigest },
|
|
1827
|
+
evidence: { ...evidence, ...(evidenceTarget ? { targetTenantId: evidenceTarget } : {}) },
|
|
1828
|
+
repositoryId: '12345',
|
|
1829
|
+
repoId: '12345',
|
|
1830
|
+
expiresAt: expiry,
|
|
1831
|
+
expiry,
|
|
1832
|
+
});
|
|
1833
|
+
for (const target of ['', 'hosting-tenant']) {
|
|
1834
|
+
const expectedTarget = target || tenantId;
|
|
1835
|
+
const tuple = ['eai.source-unknown-local-e2e-aud.v1', origin, tenantId,
|
|
1836
|
+
expectedTarget, 'rates-review', evidence.operationId, '12345',
|
|
1837
|
+
evidence.workflowPath, evidence.ref, evidence.commitSha, evidence.configHash,
|
|
1838
|
+
nonceDigest, expiry];
|
|
1839
|
+
const expected = `api://enterprise-ai-publicapi/source-unknown/local-v1/${digest(JSON.stringify(tuple))}`;
|
|
1840
|
+
for (const snippet of snippets) {
|
|
1841
|
+
assert.equal(audienceFor(snippet, target, target), expected);
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
assert.notEqual(audienceFor(snippets[1], 'hosting-tenant', 'other-tenant'),
|
|
1845
|
+
audienceFor(snippets[0], 'hosting-tenant', 'other-tenant'));
|
|
1846
|
+
});
|
|
1847
|
+
|
|
1750
1848
|
test('source commit is resolved before checkout for direct and reusable calls', () => {
|
|
1751
1849
|
const workflow = readFileSync(workflowPath, 'utf8');
|
|
1752
1850
|
const stepStart = workflow.indexOf(' - name: Validate workflow invocation');
|
|
@@ -185,6 +185,24 @@ Confirm the sign-in method separately: EAI sign-in or client SSO through EAI. Ve
|
|
|
185
185
|
7. After any `eai` error, run `eai errors explain <code-or-reason> --format json` when available before guessing remediation.
|
|
186
186
|
8. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local `.env` values into artifacts.
|
|
187
187
|
|
|
188
|
+
## Support after an unresolved EAI error
|
|
189
|
+
|
|
190
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
191
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
192
|
+
If the command still fails, prepare a report with
|
|
193
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
194
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
195
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
196
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
197
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
198
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
199
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
200
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
201
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
202
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
203
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
204
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
205
|
+
|
|
188
206
|
## Verified EAI CLI Command Contract
|
|
189
207
|
|
|
190
208
|
Do not invent, guess, or complete EAI CLI commands from memory.
|
|
@@ -277,6 +295,8 @@ The EAI Platform supports every step with secure data, identity, multi-tenancy,
|
|
|
277
295
|
|
|
278
296
|
I’ll walk you through the whole process and ask short questions as we go. Tell me what you want me to do, or ask **“What’s next?”**, **“What else can you help with?”**, or **“Show me the admin screen.”**
|
|
279
297
|
|
|
298
|
+
If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
299
|
+
|
|
280
300
|
**First question:** What process would you like to improve, or what would you like the application to help people do?
|
|
281
301
|
```
|
|
282
302
|
|
|
@@ -175,6 +175,24 @@ Confirm the sign-in method separately: EAI sign-in or client SSO through EAI. Ve
|
|
|
175
175
|
7. After any `eai` error, run `eai errors explain <code-or-reason> --format json` when available before guessing remediation.
|
|
176
176
|
8. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local `.env` values into artifacts.
|
|
177
177
|
|
|
178
|
+
## Support after an unresolved EAI error
|
|
179
|
+
|
|
180
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
181
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
182
|
+
If the command still fails, prepare a report with
|
|
183
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
184
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
185
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
186
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
187
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
188
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
189
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
190
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
191
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
192
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
193
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
194
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
195
|
+
|
|
178
196
|
## Verified EAI CLI Command Contract
|
|
179
197
|
|
|
180
198
|
Do not invent, guess, or complete EAI CLI commands from memory.
|
|
@@ -267,6 +285,8 @@ The EAI Platform supports every step with secure data, identity, multi-tenancy,
|
|
|
267
285
|
|
|
268
286
|
I’ll walk you through the whole process and ask short questions as we go. Tell me what you want me to do, or ask **“What’s next?”**, **“What else can you help with?”**, or **“Show me the admin screen.”**
|
|
269
287
|
|
|
288
|
+
If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
289
|
+
|
|
270
290
|
**First question:** What process would you like to improve, or what would you like the application to help people do?
|
|
271
291
|
```
|
|
272
292
|
|
|
@@ -185,6 +185,24 @@ Confirm the sign-in method separately: EAI sign-in or client SSO through EAI. Ve
|
|
|
185
185
|
7. After any `eai` error, run `eai errors explain <code-or-reason> --format json` when available before guessing remediation.
|
|
186
186
|
8. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local `.env` values into artifacts.
|
|
187
187
|
|
|
188
|
+
## Support after an unresolved EAI error
|
|
189
|
+
|
|
190
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
191
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
192
|
+
If the command still fails, prepare a report with
|
|
193
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
194
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
195
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
196
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
197
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
198
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
199
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
200
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
201
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
202
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
203
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
204
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
205
|
+
|
|
188
206
|
## Verified EAI CLI Command Contract
|
|
189
207
|
|
|
190
208
|
Do not invent, guess, or complete EAI CLI commands from memory.
|
|
@@ -277,6 +295,8 @@ The EAI Platform supports every step with secure data, identity, multi-tenancy,
|
|
|
277
295
|
|
|
278
296
|
I’ll walk you through the whole process and ask short questions as we go. Tell me what you want me to do, or ask **“What’s next?”**, **“What else can you help with?”**, or **“Show me the admin screen.”**
|
|
279
297
|
|
|
298
|
+
If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
299
|
+
|
|
280
300
|
**First question:** What process would you like to improve, or what would you like the application to help people do?
|
|
281
301
|
```
|
|
282
302
|
|
|
@@ -333,6 +333,24 @@ in `{FEATURE_DIR}/service-fit-matrix.md` as `unavailable without new platform
|
|
|
333
333
|
work`, `operator_required`, or `upgrade_required`. Do not silently replace it
|
|
334
334
|
with an unrelated non-EAI stack.
|
|
335
335
|
|
|
336
|
+
## Support after an unresolved EAI error
|
|
337
|
+
|
|
338
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
339
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
340
|
+
If the command still fails, prepare a report with
|
|
341
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
342
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
343
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
344
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
345
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
346
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
347
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
348
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
349
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
350
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
351
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
352
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
353
|
+
|
|
336
354
|
### EAI Preflight Checks
|
|
337
355
|
|
|
338
356
|
1. **Classify the build path**
|
|
@@ -340,6 +340,24 @@ Specifically note whether the installed CLI advertises the commands needed for:
|
|
|
340
340
|
- AI-agent guidance via `eai agent guide`
|
|
341
341
|
- error recovery guidance via `eai errors explain`
|
|
342
342
|
|
|
343
|
+
## Support after an unresolved EAI error
|
|
344
|
+
|
|
345
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
346
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
347
|
+
If the command still fails, prepare a report with
|
|
348
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
349
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
350
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
351
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
352
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
353
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
354
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
355
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
356
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
357
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
358
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
359
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
360
|
+
|
|
343
361
|
## Step 5: Login, Workspace, And Account Readiness
|
|
344
362
|
|
|
345
363
|
Run:
|
|
@@ -187,6 +187,24 @@ Confirm the sign-in method separately: EAI sign-in or client SSO through EAI. Ve
|
|
|
187
187
|
7. After any `eai` error, run `eai errors explain <code-or-reason> --format json` when available before guessing remediation.
|
|
188
188
|
8. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local `.env` values into artifacts.
|
|
189
189
|
|
|
190
|
+
## Support after an unresolved EAI error
|
|
191
|
+
|
|
192
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
193
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
194
|
+
If the command still fails, prepare a report with
|
|
195
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
196
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
197
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
198
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
199
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
200
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
201
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
202
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
203
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
204
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
205
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
206
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
207
|
+
|
|
190
208
|
## Verified EAI CLI Command Contract
|
|
191
209
|
|
|
192
210
|
Do not invent, guess, or complete EAI CLI commands from memory.
|
|
@@ -279,6 +297,8 @@ The EAI Platform supports every step with secure data, identity, multi-tenancy,
|
|
|
279
297
|
|
|
280
298
|
I’ll walk you through the whole process and ask short questions as we go. Tell me what you want me to do, or ask **“What’s next?”**, **“What else can you help with?”**, or **“Show me the admin screen.”**
|
|
281
299
|
|
|
300
|
+
If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
301
|
+
|
|
282
302
|
**First question:** What process would you like to improve, or what would you like the application to help people do?
|
|
283
303
|
```
|
|
284
304
|
|
|
@@ -177,6 +177,24 @@ Confirm the sign-in method separately: EAI sign-in or client SSO through EAI. Ve
|
|
|
177
177
|
7. After any `eai` error, run `eai errors explain <code-or-reason> --format json` when available before guessing remediation.
|
|
178
178
|
8. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local `.env` values into artifacts.
|
|
179
179
|
|
|
180
|
+
## Support after an unresolved EAI error
|
|
181
|
+
|
|
182
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
183
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
184
|
+
If the command still fails, prepare a report with
|
|
185
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
186
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
187
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
188
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
189
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
190
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
191
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
192
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
193
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
194
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
195
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
196
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
197
|
+
|
|
180
198
|
## Verified EAI CLI Command Contract
|
|
181
199
|
|
|
182
200
|
Do not invent, guess, or complete EAI CLI commands from memory.
|
|
@@ -269,6 +287,8 @@ The EAI Platform supports every step with secure data, identity, multi-tenancy,
|
|
|
269
287
|
|
|
270
288
|
I’ll walk you through the whole process and ask short questions as we go. Tell me what you want me to do, or ask **“What’s next?”**, **“What else can you help with?”**, or **“Show me the admin screen.”**
|
|
271
289
|
|
|
290
|
+
If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
291
|
+
|
|
272
292
|
**First question:** What process would you like to improve, or what would you like the application to help people do?
|
|
273
293
|
```
|
|
274
294
|
|
|
@@ -185,6 +185,24 @@ Confirm the sign-in method separately: EAI sign-in or client SSO through EAI. Ve
|
|
|
185
185
|
7. After any `eai` error, run `eai errors explain <code-or-reason> --format json` when available before guessing remediation.
|
|
186
186
|
8. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local `.env` values into artifacts.
|
|
187
187
|
|
|
188
|
+
## Support after an unresolved EAI error
|
|
189
|
+
|
|
190
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
191
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
192
|
+
If the command still fails, prepare a report with
|
|
193
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
194
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
195
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
196
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
197
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
198
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
199
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
200
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
201
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
202
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
203
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
204
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
205
|
+
|
|
188
206
|
## Verified EAI CLI Command Contract
|
|
189
207
|
|
|
190
208
|
Do not invent, guess, or complete EAI CLI commands from memory.
|
|
@@ -277,6 +295,8 @@ The EAI Platform supports every step with secure data, identity, multi-tenancy,
|
|
|
277
295
|
|
|
278
296
|
I’ll walk you through the whole process and ask short questions as we go. Tell me what you want me to do, or ask **“What’s next?”**, **“What else can you help with?”**, or **“Show me the admin screen.”**
|
|
279
297
|
|
|
298
|
+
If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
299
|
+
|
|
280
300
|
**First question:** What process would you like to improve, or what would you like the application to help people do?
|
|
281
301
|
```
|
|
282
302
|
|
|
@@ -185,6 +185,24 @@ Confirm the sign-in method separately: EAI sign-in or client SSO through EAI. Ve
|
|
|
185
185
|
7. After any `eai` error, run `eai errors explain <code-or-reason> --format json` when available before guessing remediation.
|
|
186
186
|
8. Do not write tokens, secrets, private workspace IDs, Entra/CIAM authority tenant IDs, or local `.env` values into artifacts.
|
|
187
187
|
|
|
188
|
+
## Support after an unresolved EAI error
|
|
189
|
+
|
|
190
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
191
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
192
|
+
If the command still fails, prepare a report with
|
|
193
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
194
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
195
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
196
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
197
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
198
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
199
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
200
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
201
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
202
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
203
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
204
|
+
If the person asks for help with a silent failure, start with the same report preview.
|
|
205
|
+
|
|
188
206
|
## Verified EAI CLI Command Contract
|
|
189
207
|
|
|
190
208
|
Do not invent, guess, or complete EAI CLI commands from memory.
|
|
@@ -277,6 +295,8 @@ The EAI Platform supports every step with secure data, identity, multi-tenancy,
|
|
|
277
295
|
|
|
278
296
|
I’ll walk you through the whole process and ask short questions as we go. Tell me what you want me to do, or ask **“What’s next?”**, **“What else can you help with?”**, or **“Show me the admin screen.”**
|
|
279
297
|
|
|
298
|
+
If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
299
|
+
|
|
280
300
|
**First question:** What process would you like to improve, or what would you like the application to help people do?
|
|
281
301
|
```
|
|
282
302
|
|
|
@@ -39,3 +39,21 @@ non-app work asks once before skipping EAI tenant/app setup. Artifacts in
|
|
|
39
39
|
standards.
|
|
40
40
|
- **Minimal Impact**: Changes should only touch what's necessary. Avoid
|
|
41
41
|
introducing bugs.
|
|
42
|
+
|
|
43
|
+
## Support after an unresolved EAI error
|
|
44
|
+
|
|
45
|
+
After an `eai` command fails, run `eai errors explain <code-or-reason> --format json`.
|
|
46
|
+
Follow its diagnostics, approval requirements, and fixes once. Stop at its retry limit.
|
|
47
|
+
If the command still fails, prepare a report with
|
|
48
|
+
`eai support --source harness --tool <current-tool> --format json`.
|
|
49
|
+
Use `codex`, `claude`, `vscode`, `grok`, or `antigravity` for `<current-tool>`.
|
|
50
|
+
This command previews the locally redacted bundle in a noninteractive harness.
|
|
51
|
+
Show the person the bundle summary and ask for explicit consent in the chat.
|
|
52
|
+
Only after they approve that bundle, repeat the command with `--yes --no-open` and give them the returned link.
|
|
53
|
+
If the bundle changes, show it again and ask for fresh consent. Never assume consent or run `--yes` automatically.
|
|
54
|
+
Keep secrets, tokens, raw logs, and local `.env` values out of the chat.
|
|
55
|
+
The CLI creates the draft; the AI never calls the support API itself.
|
|
56
|
+
Report content stays in the draft body. The Support link fragment carries only its id and token.
|
|
57
|
+
If sign-in is unavailable, give the person the plain Support page link returned by the CLI.
|
|
58
|
+
In the welcome reply, say: If anything fails, say "get help" or type `eai support`; I can prepare a report for you to approve.
|
|
59
|
+
If the person asks for help with a silent failure, start with the same report preview.
|