swipium 1.0.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/LICENSE +21 -0
- package/README.md +295 -0
- package/dist/appMap/automationLink.js +74 -0
- package/dist/appMap/automationLink.js.map +1 -0
- package/dist/appMap/build.js +193 -0
- package/dist/appMap/build.js.map +1 -0
- package/dist/appMap/codeIndex.js +73 -0
- package/dist/appMap/codeIndex.js.map +1 -0
- package/dist/appMap/featureModel.js +83 -0
- package/dist/appMap/featureModel.js.map +1 -0
- package/dist/appMap/firstRunApply.js +131 -0
- package/dist/appMap/firstRunApply.js.map +1 -0
- package/dist/appMap/fsWalk.js +75 -0
- package/dist/appMap/fsWalk.js.map +1 -0
- package/dist/appMap/issues.js +227 -0
- package/dist/appMap/issues.js.map +1 -0
- package/dist/appMap/migrations.js +87 -0
- package/dist/appMap/migrations.js.map +1 -0
- package/dist/appMap/prelaunch.js +66 -0
- package/dist/appMap/prelaunch.js.map +1 -0
- package/dist/appMap/projectRegistry.js +70 -0
- package/dist/appMap/projectRegistry.js.map +1 -0
- package/dist/appMap/provenance.js +52 -0
- package/dist/appMap/provenance.js.map +1 -0
- package/dist/appMap/query.js +118 -0
- package/dist/appMap/query.js.map +1 -0
- package/dist/appMap/runtimeMerge.js +207 -0
- package/dist/appMap/runtimeMerge.js.map +1 -0
- package/dist/appMap/schema.js +65 -0
- package/dist/appMap/schema.js.map +1 -0
- package/dist/appMap/screenMatch.js +75 -0
- package/dist/appMap/screenMatch.js.map +1 -0
- package/dist/appMap/staticScan.js +614 -0
- package/dist/appMap/staticScan.js.map +1 -0
- package/dist/appMap/store.js +173 -0
- package/dist/appMap/store.js.map +1 -0
- package/dist/appMap/tsAstScan.js +184 -0
- package/dist/appMap/tsAstScan.js.map +1 -0
- package/dist/artifacts/bundletool.js +199 -0
- package/dist/artifacts/bundletool.js.map +1 -0
- package/dist/artifacts/resolve.js +388 -0
- package/dist/artifacts/resolve.js.map +1 -0
- package/dist/automationGen/appiumModel.js +129 -0
- package/dist/automationGen/appiumModel.js.map +1 -0
- package/dist/automationGen/ciEmitter.js +80 -0
- package/dist/automationGen/ciEmitter.js.map +1 -0
- package/dist/automationGen/jsEmitter.js +440 -0
- package/dist/automationGen/jsEmitter.js.map +1 -0
- package/dist/automationGen/packagePatch.js +56 -0
- package/dist/automationGen/packagePatch.js.map +1 -0
- package/dist/automationGen/projectProfile.js +317 -0
- package/dist/automationGen/projectProfile.js.map +1 -0
- package/dist/automationGen/pythonEmitter.js +386 -0
- package/dist/automationGen/pythonEmitter.js.map +1 -0
- package/dist/automationGen/readmeEmitter.js +66 -0
- package/dist/automationGen/readmeEmitter.js.map +1 -0
- package/dist/automationGen/suitePlan.js +94 -0
- package/dist/automationGen/suitePlan.js.map +1 -0
- package/dist/automationGen/validation.js +150 -0
- package/dist/automationGen/validation.js.map +1 -0
- package/dist/build/parseBuildLog.js +119 -0
- package/dist/build/parseBuildLog.js.map +1 -0
- package/dist/build/plan.js +150 -0
- package/dist/build/plan.js.map +1 -0
- package/dist/ci/preflight.js +85 -0
- package/dist/ci/preflight.js.map +1 -0
- package/dist/cli/init.js +105 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/scan.js +85 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/suite.js +85 -0
- package/dist/cli/suite.js.map +1 -0
- package/dist/cli/verify.js +62 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/consent/consent.js +43 -0
- package/dist/consent/consent.js.map +1 -0
- package/dist/context/detect.js +156 -0
- package/dist/context/detect.js.map +1 -0
- package/dist/context/findApps.js +198 -0
- package/dist/context/findApps.js.map +1 -0
- package/dist/context/projectRoot.js +41 -0
- package/dist/context/projectRoot.js.map +1 -0
- package/dist/context/scan.js +167 -0
- package/dist/context/scan.js.map +1 -0
- package/dist/core/target.js +115 -0
- package/dist/core/target.js.map +1 -0
- package/dist/core/targetPlan.js +140 -0
- package/dist/core/targetPlan.js.map +1 -0
- package/dist/drivers/DirectDriver.js +228 -0
- package/dist/drivers/DirectDriver.js.map +1 -0
- package/dist/drivers/Driver.js +4 -0
- package/dist/drivers/Driver.js.map +1 -0
- package/dist/drivers/SimctlDriver.js +127 -0
- package/dist/drivers/SimctlDriver.js.map +1 -0
- package/dist/drivers/WdaDriver.js +250 -0
- package/dist/drivers/WdaDriver.js.map +1 -0
- package/dist/explore/candidates.js +93 -0
- package/dist/explore/candidates.js.map +1 -0
- package/dist/explore/graph.js +116 -0
- package/dist/explore/graph.js.map +1 -0
- package/dist/explore/memory.js +35 -0
- package/dist/explore/memory.js.map +1 -0
- package/dist/explore/planner.js +105 -0
- package/dist/explore/planner.js.map +1 -0
- package/dist/explore/policy.js +85 -0
- package/dist/explore/policy.js.map +1 -0
- package/dist/explore/runner.js +475 -0
- package/dist/explore/runner.js.map +1 -0
- package/dist/explore/signatures.js +35 -0
- package/dist/explore/signatures.js.map +1 -0
- package/dist/explore/suite.js +55 -0
- package/dist/explore/suite.js.map +1 -0
- package/dist/featureTesting/executionBootstrap.js +140 -0
- package/dist/featureTesting/executionBootstrap.js.map +1 -0
- package/dist/firstRun/authStateMachine.js +83 -0
- package/dist/firstRun/authStateMachine.js.map +1 -0
- package/dist/firstRun/classifyScreen.js +201 -0
- package/dist/firstRun/classifyScreen.js.map +1 -0
- package/dist/firstRun/firstRunPlanner.js +207 -0
- package/dist/firstRun/firstRunPlanner.js.map +1 -0
- package/dist/firstRun/firstRunRunner.js +331 -0
- package/dist/firstRun/firstRunRunner.js.map +1 -0
- package/dist/firstRun/generatedDataPolicy.js +215 -0
- package/dist/firstRun/generatedDataPolicy.js.map +1 -0
- package/dist/firstRun/inputPlanner.js +67 -0
- package/dist/firstRun/inputPlanner.js.map +1 -0
- package/dist/firstRun/onboardingStateMachine.js +46 -0
- package/dist/firstRun/onboardingStateMachine.js.map +1 -0
- package/dist/firstRun/paywallPolicy.js +54 -0
- package/dist/firstRun/paywallPolicy.js.map +1 -0
- package/dist/firstRun/types.js +7 -0
- package/dist/firstRun/types.js.map +1 -0
- package/dist/fixtures/catalog.js +131 -0
- package/dist/fixtures/catalog.js.map +1 -0
- package/dist/flows/discover.js +18 -0
- package/dist/flows/discover.js.map +1 -0
- package/dist/flows/generate.js +211 -0
- package/dist/flows/generate.js.map +1 -0
- package/dist/flows/lint.js +97 -0
- package/dist/flows/lint.js.map +1 -0
- package/dist/flows/pack.js +68 -0
- package/dist/flows/pack.js.map +1 -0
- package/dist/flows/run.js +738 -0
- package/dist/flows/run.js.map +1 -0
- package/dist/flows/schema.js +240 -0
- package/dist/flows/schema.js.map +1 -0
- package/dist/flows/seedExec.js +108 -0
- package/dist/flows/seedExec.js.map +1 -0
- package/dist/flows/templates.js +155 -0
- package/dist/flows/templates.js.map +1 -0
- package/dist/flows/waitGuards.js +12 -0
- package/dist/flows/waitGuards.js.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/ios/signing.js +182 -0
- package/dist/ios/signing.js.map +1 -0
- package/dist/issues/classify.js +186 -0
- package/dist/issues/classify.js.map +1 -0
- package/dist/issues/fingerprint.js +130 -0
- package/dist/issues/fingerprint.js.map +1 -0
- package/dist/issues/index.js +240 -0
- package/dist/issues/index.js.map +1 -0
- package/dist/issues/metrics.js +155 -0
- package/dist/issues/metrics.js.map +1 -0
- package/dist/issues/recurrence.js +193 -0
- package/dist/issues/recurrence.js.map +1 -0
- package/dist/issues/report.js +110 -0
- package/dist/issues/report.js.map +1 -0
- package/dist/issues/reportBridge.js +119 -0
- package/dist/issues/reportBridge.js.map +1 -0
- package/dist/issues/schema.js +90 -0
- package/dist/issues/schema.js.map +1 -0
- package/dist/issues/sourceRevision.js +108 -0
- package/dist/issues/sourceRevision.js.map +1 -0
- package/dist/issues/store.js +155 -0
- package/dist/issues/store.js.map +1 -0
- package/dist/lib/android.js +278 -0
- package/dist/lib/android.js.map +1 -0
- package/dist/lib/commandTemplate.js +55 -0
- package/dist/lib/commandTemplate.js.map +1 -0
- package/dist/lib/coordSpace.js +23 -0
- package/dist/lib/coordSpace.js.map +1 -0
- package/dist/lib/device.js +87 -0
- package/dist/lib/device.js.map +1 -0
- package/dist/lib/gitignore.js +22 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/image.js +97 -0
- package/dist/lib/image.js.map +1 -0
- package/dist/lib/logger.js +8 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/metroState.js +45 -0
- package/dist/lib/metroState.js.map +1 -0
- package/dist/lib/needsInput.js +201 -0
- package/dist/lib/needsInput.js.map +1 -0
- package/dist/lib/png.js +103 -0
- package/dist/lib/png.js.map +1 -0
- package/dist/lib/redact.js +21 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/result.js +87 -0
- package/dist/lib/result.js.map +1 -0
- package/dist/lib/schemaHash.js +65 -0
- package/dist/lib/schemaHash.js.map +1 -0
- package/dist/lib/sensitive.js +13 -0
- package/dist/lib/sensitive.js.map +1 -0
- package/dist/lib/simctl.js +149 -0
- package/dist/lib/simctl.js.map +1 -0
- package/dist/lib/spawn.js +144 -0
- package/dist/lib/spawn.js.map +1 -0
- package/dist/lib/wda.js +347 -0
- package/dist/lib/wda.js.map +1 -0
- package/dist/lib/wdaConfig.js +69 -0
- package/dist/lib/wdaConfig.js.map +1 -0
- package/dist/lib/wdaTune.js +58 -0
- package/dist/lib/wdaTune.js.map +1 -0
- package/dist/oracle/auth.js +22 -0
- package/dist/oracle/auth.js.map +1 -0
- package/dist/oracle/failures.js +193 -0
- package/dist/oracle/failures.js.map +1 -0
- package/dist/oracle/health.js +123 -0
- package/dist/oracle/health.js.map +1 -0
- package/dist/oracle/record.js +36 -0
- package/dist/oracle/record.js.map +1 -0
- package/dist/orchestration/envelope.js +52 -0
- package/dist/orchestration/envelope.js.map +1 -0
- package/dist/orchestration/goal.js +98 -0
- package/dist/orchestration/goal.js.map +1 -0
- package/dist/plan/plan.js +124 -0
- package/dist/plan/plan.js.map +1 -0
- package/dist/prompts/index.js +63 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/report/artifactManifest.js +44 -0
- package/dist/report/artifactManifest.js.map +1 -0
- package/dist/report/coverage.js +60 -0
- package/dist/report/coverage.js.map +1 -0
- package/dist/report/evidence.js +84 -0
- package/dist/report/evidence.js.map +1 -0
- package/dist/report/export.js +447 -0
- package/dist/report/export.js.map +1 -0
- package/dist/report/flake.js +61 -0
- package/dist/report/flake.js.map +1 -0
- package/dist/report/history.js +564 -0
- package/dist/report/history.js.map +1 -0
- package/dist/report/policy.js +98 -0
- package/dist/report/policy.js.map +1 -0
- package/dist/report/qaLevel.js +96 -0
- package/dist/report/qaLevel.js.map +1 -0
- package/dist/report/readiness.js +213 -0
- package/dist/report/readiness.js.map +1 -0
- package/dist/report/summary.js +42 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/report/testCatalog.js +93 -0
- package/dist/report/testCatalog.js.map +1 -0
- package/dist/report/timing.js +37 -0
- package/dist/report/timing.js.map +1 -0
- package/dist/server.js +180 -0
- package/dist/server.js.map +1 -0
- package/dist/services/automationGenerate.js +60 -0
- package/dist/services/automationGenerate.js.map +1 -0
- package/dist/services/build.js +66 -0
- package/dist/services/build.js.map +1 -0
- package/dist/services/preflight.js +51 -0
- package/dist/services/preflight.js.map +1 -0
- package/dist/services/prepareAndroid.js +183 -0
- package/dist/services/prepareAndroid.js.map +1 -0
- package/dist/services/prepareIos.js +162 -0
- package/dist/services/prepareIos.js.map +1 -0
- package/dist/services/report.js +537 -0
- package/dist/services/report.js.map +1 -0
- package/dist/services/smoke.js +120 -0
- package/dist/services/smoke.js.map +1 -0
- package/dist/services/suiteGenerate.js +123 -0
- package/dist/services/suiteGenerate.js.map +1 -0
- package/dist/services/testSuiteKnowledge.js +150 -0
- package/dist/services/testSuiteKnowledge.js.map +1 -0
- package/dist/session/attach.js +47 -0
- package/dist/session/attach.js.map +1 -0
- package/dist/session/progress.js +56 -0
- package/dist/session/progress.js.map +1 -0
- package/dist/session/store.js +329 -0
- package/dist/session/store.js.map +1 -0
- package/dist/snapshot/overlays.js +132 -0
- package/dist/snapshot/overlays.js.map +1 -0
- package/dist/snapshot/parse.js +204 -0
- package/dist/snapshot/parse.js.map +1 -0
- package/dist/snapshot/present.js +12 -0
- package/dist/snapshot/present.js.map +1 -0
- package/dist/snapshot/settle.js +36 -0
- package/dist/snapshot/settle.js.map +1 -0
- package/dist/state/profile.js +318 -0
- package/dist/state/profile.js.map +1 -0
- package/dist/suite/compile.js +176 -0
- package/dist/suite/compile.js.map +1 -0
- package/dist/suite/lint.js +45 -0
- package/dist/suite/lint.js.map +1 -0
- package/dist/suite/pom.js +285 -0
- package/dist/suite/pom.js.map +1 -0
- package/dist/suite/testcase.js +87 -0
- package/dist/suite/testcase.js.map +1 -0
- package/dist/testSuite/generator.js +222 -0
- package/dist/testSuite/generator.js.map +1 -0
- package/dist/testSuite/history.js +44 -0
- package/dist/testSuite/history.js.map +1 -0
- package/dist/testSuite/issueLinks.js +96 -0
- package/dist/testSuite/issueLinks.js.map +1 -0
- package/dist/testSuite/merge.js +190 -0
- package/dist/testSuite/merge.js.map +1 -0
- package/dist/testSuite/schema.js +86 -0
- package/dist/testSuite/schema.js.map +1 -0
- package/dist/testSuite/store.js +116 -0
- package/dist/testSuite/store.js.map +1 -0
- package/dist/testSuite/traceability.js +55 -0
- package/dist/testSuite/traceability.js.map +1 -0
- package/dist/tools/act.js +457 -0
- package/dist/tools/act.js.map +1 -0
- package/dist/tools/agent.js +225 -0
- package/dist/tools/agent.js.map +1 -0
- package/dist/tools/appMap.js +317 -0
- package/dist/tools/appMap.js.map +1 -0
- package/dist/tools/assertVisual.js +74 -0
- package/dist/tools/assertVisual.js.map +1 -0
- package/dist/tools/automationGenerate.js +394 -0
- package/dist/tools/automationGenerate.js.map +1 -0
- package/dist/tools/capabilities.js +114 -0
- package/dist/tools/capabilities.js.map +1 -0
- package/dist/tools/clearOverlay.js +150 -0
- package/dist/tools/clearOverlay.js.map +1 -0
- package/dist/tools/detectContext.js +41 -0
- package/dist/tools/detectContext.js.map +1 -0
- package/dist/tools/doctor.js +116 -0
- package/dist/tools/doctor.js.map +1 -0
- package/dist/tools/explore.js +289 -0
- package/dist/tools/explore.js.map +1 -0
- package/dist/tools/firstRun.js +136 -0
- package/dist/tools/firstRun.js.map +1 -0
- package/dist/tools/flow.js +331 -0
- package/dist/tools/flow.js.map +1 -0
- package/dist/tools/flowGenerate.js +55 -0
- package/dist/tools/flowGenerate.js.map +1 -0
- package/dist/tools/getArtifact.js +39 -0
- package/dist/tools/getArtifact.js.map +1 -0
- package/dist/tools/health.js +41 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/ios.js +492 -0
- package/dist/tools/ios.js.map +1 -0
- package/dist/tools/jobs.js +20 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/network.js +50 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/note.js +69 -0
- package/dist/tools/note.js.map +1 -0
- package/dist/tools/plan.js +49 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/prepareIosTarget.js +99 -0
- package/dist/tools/prepareIosTarget.js.map +1 -0
- package/dist/tools/prepareTarget.js +257 -0
- package/dist/tools/prepareTarget.js.map +1 -0
- package/dist/tools/report.js +42 -0
- package/dist/tools/report.js.map +1 -0
- package/dist/tools/screenRecord.js +24 -0
- package/dist/tools/screenRecord.js.map +1 -0
- package/dist/tools/screenshot.js +63 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/smoke.js +39 -0
- package/dist/tools/smoke.js.map +1 -0
- package/dist/tools/snapshot.js +129 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/tools/startSession.js +169 -0
- package/dist/tools/startSession.js.map +1 -0
- package/dist/tools/state.js +87 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/tools/suite.js +412 -0
- package/dist/tools/suite.js.map +1 -0
- package/dist/tools/testThis.js +774 -0
- package/dist/tools/testThis.js.map +1 -0
- package/dist/tools/wda.js +477 -0
- package/dist/tools/wda.js.map +1 -0
- package/dist/version.js +62 -0
- package/dist/version.js.map +1 -0
- package/dist/visual/ocr.js +72 -0
- package/dist/visual/ocr.js.map +1 -0
- package/dist/visual/provider.js +75 -0
- package/dist/visual/provider.js.map +1 -0
- package/docs/README.md +19 -0
- package/docs/assets/swipium-lockup-ink-on-light.png +0 -0
- package/docs/mcp-server.md +135 -0
- package/docs/tools.md +130 -0
- package/package.json +70 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// SWIPIUM-REQ-02 — safe generated-data policy + environment classifier + built-in safe generators.
|
|
2
|
+
//
|
|
3
|
+
// Controlled autonomy: Swipium will only invent values for input fields (to create a throwaway
|
|
4
|
+
// account, fill onboarding, etc.) when policy AND the classified environment say it is safe. The
|
|
5
|
+
// guardrails follow the MCP security best-practices (consent, least privilege) and Anthropic's
|
|
6
|
+
// "use environmental ground truth at each step" guidance — if production cannot be ruled out we do
|
|
7
|
+
// NOT create an account; we ask one NeedsInput question instead.
|
|
8
|
+
//
|
|
9
|
+
// Secrets (generated passwords) are flagged so they go into the session redaction set and never
|
|
10
|
+
// appear in reports/artifacts/app map. Generated emails are non-secret and recorded as evidence so
|
|
11
|
+
// a developer can reproduce the throwaway account.
|
|
12
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
export const DEFAULT_TEST_DATA_POLICY = {
|
|
15
|
+
schemaVersion: 1,
|
|
16
|
+
allowGeneratedAccounts: 'test_or_staging_only',
|
|
17
|
+
email: {
|
|
18
|
+
generator: 'swipium_timestamp',
|
|
19
|
+
pattern: 'swipium_<timestamp>@yopmail.com',
|
|
20
|
+
externalMailboxProvider: 'yopmail',
|
|
21
|
+
requiresNetwork: true,
|
|
22
|
+
},
|
|
23
|
+
password: {
|
|
24
|
+
generator: 'strong_default',
|
|
25
|
+
value: 'Celtics1230!',
|
|
26
|
+
secret: true,
|
|
27
|
+
},
|
|
28
|
+
allowPhone: false,
|
|
29
|
+
allowDateOfBirth: false,
|
|
30
|
+
forbiddenEnvironments: ['production'],
|
|
31
|
+
requiresDisposableStateForDestructiveActions: true,
|
|
32
|
+
recordGeneratedValues: true,
|
|
33
|
+
cleanup: {
|
|
34
|
+
requiredWhenSupported: true,
|
|
35
|
+
strategy: 'app_or_api_if_declared',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
export const DEFAULT_POLICY_PATH = '.swipium/test-data-policy.json';
|
|
39
|
+
/** Load `.swipium/test-data-policy.json` from the project root (or an explicit path), deep-merged
|
|
40
|
+
* over the safe default. A missing/corrupt file falls back to the default — never throws. */
|
|
41
|
+
export function loadTestDataPolicy(root, explicitPath) {
|
|
42
|
+
const path = explicitPath
|
|
43
|
+
? (explicitPath.startsWith('/') ? explicitPath : join(root, explicitPath))
|
|
44
|
+
: join(root, DEFAULT_POLICY_PATH);
|
|
45
|
+
if (!existsSync(path))
|
|
46
|
+
return { policy: DEFAULT_TEST_DATA_POLICY, source: 'default' };
|
|
47
|
+
try {
|
|
48
|
+
const raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
49
|
+
const policy = {
|
|
50
|
+
...DEFAULT_TEST_DATA_POLICY,
|
|
51
|
+
...raw,
|
|
52
|
+
email: { ...DEFAULT_TEST_DATA_POLICY.email, ...(raw.email ?? {}) },
|
|
53
|
+
password: { ...DEFAULT_TEST_DATA_POLICY.password, ...(raw.password ?? {}) },
|
|
54
|
+
cleanup: { ...DEFAULT_TEST_DATA_POLICY.cleanup, ...(raw.cleanup ?? {}) },
|
|
55
|
+
forbiddenEnvironments: raw.forbiddenEnvironments ?? DEFAULT_TEST_DATA_POLICY.forbiddenEnvironments,
|
|
56
|
+
};
|
|
57
|
+
return { policy, source: path };
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return { policy: DEFAULT_TEST_DATA_POLICY, source: 'default (unreadable policy file)' };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const TEST_TOKEN = /\b(test|qa|uat|sandbox|staging|stage|dev|develop|development|debug|internal|preview|nonprod|non-prod)\b/i;
|
|
64
|
+
const STAGING_TOKEN = /\b(staging|stage|uat|preprod|pre-prod)\b/i;
|
|
65
|
+
const PROD_TOKEN = /\b(prod|production|release|live|www)\b/i;
|
|
66
|
+
const PROD_HOST = /https?:\/\/(?:api\.|www\.)?(?!.*(?:staging|stage|test|qa|uat|sandbox|dev|preprod|localhost|127\.0\.0\.1|10\.|192\.168)).+\.(?:com|net|org|io|app|co)\b/i;
|
|
67
|
+
/** Classify the environment from app id / build / config signals. Conservative: when nothing rules
|
|
68
|
+
* production out, `productionRisk` is true so the caller asks before creating an account. */
|
|
69
|
+
export function classifyEnvironment(input) {
|
|
70
|
+
const signals = [];
|
|
71
|
+
// 1. An explicitly declared disposable/test fixture is authoritative.
|
|
72
|
+
if (input.declaredEnvironment) {
|
|
73
|
+
const env = input.declaredEnvironment.toLowerCase();
|
|
74
|
+
if (env === 'production' || env === 'prod' || env === 'live') {
|
|
75
|
+
signals.push('fixture declares environment=production');
|
|
76
|
+
return { environment: 'production', confidence: 0.95, signals, productionRisk: true };
|
|
77
|
+
}
|
|
78
|
+
if (env === 'staging') {
|
|
79
|
+
signals.push('fixture declares environment=staging');
|
|
80
|
+
return { environment: 'staging', confidence: 0.9, signals, productionRisk: false };
|
|
81
|
+
}
|
|
82
|
+
signals.push(`fixture declares environment=${env}`);
|
|
83
|
+
return { environment: 'test', confidence: 0.9, signals, productionRisk: false };
|
|
84
|
+
}
|
|
85
|
+
if (input.hasDisposableState) {
|
|
86
|
+
signals.push('a disposable/test fixture is declared for this session');
|
|
87
|
+
return { environment: 'test', confidence: 0.85, signals, productionRisk: false };
|
|
88
|
+
}
|
|
89
|
+
const idHay = `${input.appId ?? ''}`;
|
|
90
|
+
const apiHay = (input.apiBaseUrls ?? []).join(' ');
|
|
91
|
+
const cfgHay = `${input.configText ?? ''}`;
|
|
92
|
+
// 2. Production signals (any one of these flips productionRisk on).
|
|
93
|
+
let prodHits = 0;
|
|
94
|
+
if (PROD_TOKEN.test(idHay)) {
|
|
95
|
+
signals.push(`app id "${input.appId}" contains a production-like token`);
|
|
96
|
+
prodHits++;
|
|
97
|
+
}
|
|
98
|
+
for (const url of input.apiBaseUrls ?? []) {
|
|
99
|
+
if (STAGING_TOKEN.test(url) || TEST_TOKEN.test(url))
|
|
100
|
+
continue;
|
|
101
|
+
if (PROD_HOST.test(url) || PROD_TOKEN.test(url)) {
|
|
102
|
+
signals.push(`API base URL looks production: ${url}`);
|
|
103
|
+
prodHits++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// 3. Test/staging signals.
|
|
107
|
+
let testHits = 0;
|
|
108
|
+
let stagingHits = 0;
|
|
109
|
+
if (STAGING_TOKEN.test(idHay) || STAGING_TOKEN.test(apiHay)) {
|
|
110
|
+
signals.push('app id / API contains a staging token');
|
|
111
|
+
stagingHits++;
|
|
112
|
+
}
|
|
113
|
+
if (TEST_TOKEN.test(idHay)) {
|
|
114
|
+
signals.push(`app id "${input.appId}" contains a test/dev token`);
|
|
115
|
+
testHits++;
|
|
116
|
+
}
|
|
117
|
+
if (TEST_TOKEN.test(apiHay)) {
|
|
118
|
+
signals.push('API base URL contains a test/dev token');
|
|
119
|
+
testHits++;
|
|
120
|
+
}
|
|
121
|
+
if (input.buildType && /debug/i.test(input.buildType)) {
|
|
122
|
+
signals.push('build type is debug');
|
|
123
|
+
testHits++;
|
|
124
|
+
}
|
|
125
|
+
if (TEST_TOKEN.test(cfgHay)) {
|
|
126
|
+
signals.push('app config contains a test/dev token');
|
|
127
|
+
testHits++;
|
|
128
|
+
}
|
|
129
|
+
if (stagingHits > 0 && prodHits === 0) {
|
|
130
|
+
return { environment: 'staging', confidence: 0.75, signals, productionRisk: false };
|
|
131
|
+
}
|
|
132
|
+
if (testHits > 0 && prodHits === 0) {
|
|
133
|
+
return { environment: 'test', confidence: Math.min(0.8, 0.5 + testHits * 0.12), signals, productionRisk: false };
|
|
134
|
+
}
|
|
135
|
+
if (prodHits > 0) {
|
|
136
|
+
return { environment: 'production', confidence: Math.min(0.85, 0.55 + prodHits * 0.15), signals, productionRisk: true };
|
|
137
|
+
}
|
|
138
|
+
// 4. Nothing decisive → unknown, and we MUST treat unknown as production-risk (fail safe).
|
|
139
|
+
signals.push('no decisive test/staging signal — environment cannot be confirmed as non-production');
|
|
140
|
+
return { environment: 'unknown', confidence: 0.3, signals, productionRisk: true };
|
|
141
|
+
}
|
|
142
|
+
/** Combine policy + environment into the single "may Swipium create a throwaway account?" verdict. */
|
|
143
|
+
export function decideGeneratedAccount(policy, env, override) {
|
|
144
|
+
if (override === false) {
|
|
145
|
+
return { allowed: false, reason: 'generated-account creation was explicitly disabled for this run', environment: env };
|
|
146
|
+
}
|
|
147
|
+
if (policy.forbiddenEnvironments.map((e) => e.toLowerCase()).includes(env.environment)) {
|
|
148
|
+
return { allowed: false, reason: `policy forbids generated accounts in "${env.environment}" environments`, environment: env };
|
|
149
|
+
}
|
|
150
|
+
if (env.productionRisk && override !== true) {
|
|
151
|
+
return {
|
|
152
|
+
allowed: false,
|
|
153
|
+
reason: env.environment === 'production'
|
|
154
|
+
? 'environment classified as production — refusing automatic account creation'
|
|
155
|
+
: 'environment could not be confirmed as non-production — refusing automatic account creation',
|
|
156
|
+
environment: env,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (policy.allowGeneratedAccounts === 'never') {
|
|
160
|
+
return { allowed: false, reason: 'policy disallows generated accounts (allowGeneratedAccounts="never")', environment: env };
|
|
161
|
+
}
|
|
162
|
+
if (policy.allowGeneratedAccounts === 'always' || override === true) {
|
|
163
|
+
return { allowed: true, reason: override === true ? 'generated account explicitly approved for this run' : 'policy allows generated accounts (always)', environment: env };
|
|
164
|
+
}
|
|
165
|
+
// test_or_staging_only
|
|
166
|
+
if (env.environment === 'test' || env.environment === 'staging') {
|
|
167
|
+
return { allowed: true, reason: `policy allows generated accounts in ${env.environment} (test_or_staging_only)`, environment: env };
|
|
168
|
+
}
|
|
169
|
+
return { allowed: false, reason: `policy allows generated accounts only in test/staging; environment is "${env.environment}"`, environment: env };
|
|
170
|
+
}
|
|
171
|
+
const GIVEN_NAMES = ['Alex', 'Sam', 'Jordan', 'Taylor', 'Casey', 'Riley', 'Morgan', 'Jamie'];
|
|
172
|
+
const FAMILY_NAMES = ['Tester', 'Quality', 'Sample', 'Probe', 'Fixture'];
|
|
173
|
+
const CITIES = ['Springfield', 'Rivertown', 'Lakeview', 'Fairview', 'Brookside'];
|
|
174
|
+
function emailFromPattern(pattern, ts, index) {
|
|
175
|
+
const stamp = index != null ? `${ts}${index}` : `${ts}`;
|
|
176
|
+
return pattern.includes('<timestamp>') ? pattern.replace('<timestamp>', stamp) : `swipium_${stamp}@yopmail.com`;
|
|
177
|
+
}
|
|
178
|
+
/** Generate a safe value for a field kind under the policy. Returns undefined when the field kind
|
|
179
|
+
* is not safely generatable without explicit policy opt-in (phone/date_of_birth) or never
|
|
180
|
+
* (otp — must come from a real provider). */
|
|
181
|
+
export function generateFieldValue(field, policy, opts = {}) {
|
|
182
|
+
const ts = opts.timestamp ?? Date.now();
|
|
183
|
+
const i = opts.index;
|
|
184
|
+
switch (field) {
|
|
185
|
+
case 'email':
|
|
186
|
+
return { value: emailFromPattern(policy.email.pattern, ts, i), secret: false, generator: policy.email.generator };
|
|
187
|
+
case 'username':
|
|
188
|
+
// Derive a safe, unique handle from the email local-part so it's collision-resistant per run.
|
|
189
|
+
return { value: emailFromPattern(policy.email.pattern, ts, i).split('@')[0], secret: false, generator: 'username_default' };
|
|
190
|
+
case 'password':
|
|
191
|
+
case 'confirm_password':
|
|
192
|
+
return { value: policy.password.value, secret: policy.password.secret, generator: policy.password.generator };
|
|
193
|
+
case 'name':
|
|
194
|
+
return { value: `${GIVEN_NAMES[ts % GIVEN_NAMES.length]} ${FAMILY_NAMES[ts % FAMILY_NAMES.length]}`, secret: false, generator: 'name_default' };
|
|
195
|
+
case 'first_name':
|
|
196
|
+
return { value: GIVEN_NAMES[ts % GIVEN_NAMES.length], secret: false, generator: 'name_default' };
|
|
197
|
+
case 'last_name':
|
|
198
|
+
return { value: FAMILY_NAMES[ts % FAMILY_NAMES.length], secret: false, generator: 'name_default' };
|
|
199
|
+
case 'city':
|
|
200
|
+
return { value: CITIES[ts % CITIES.length], secret: false, generator: 'city_default' };
|
|
201
|
+
case 'address':
|
|
202
|
+
return { value: `${100 + (ts % 900)} Test Street`, secret: false, generator: 'address_default' };
|
|
203
|
+
case 'search':
|
|
204
|
+
return { value: 'test', secret: false, generator: 'search_default' };
|
|
205
|
+
case 'phone':
|
|
206
|
+
return policy.allowPhone ? { value: '+15555550123', secret: false, generator: 'phone_default' } : undefined;
|
|
207
|
+
case 'date_of_birth':
|
|
208
|
+
return policy.allowDateOfBirth ? { value: '1990-01-15', secret: false, generator: 'dob_default' } : undefined;
|
|
209
|
+
case 'otp':
|
|
210
|
+
return undefined; // never invented — only a declared provider may supply it
|
|
211
|
+
default:
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=generatedDataPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generatedDataPolicy.js","sourceRoot":"","sources":["../../src/firstRun/generatedDataPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SWIPIUM-REQ-02 — planInputForField(): decide what (if anything) to type into a field, with a
|
|
2
|
+
// strict priority order so Swipium never invents data unless policy + environment allow it.
|
|
3
|
+
//
|
|
4
|
+
// Priority:
|
|
5
|
+
// 1. Existing secure user input for the matching field (from a NeedsInput resume).
|
|
6
|
+
// 2. Declared fixture value or generator.
|
|
7
|
+
// 3. Built-in safe generator — ONLY when generated accounts are allowed for this environment.
|
|
8
|
+
// 4. NeedsInput when the value is unsafe/unknown but required.
|
|
9
|
+
// 5. Skip (blocked) when the field is optional.
|
|
10
|
+
//
|
|
11
|
+
// PURE w.r.t. the device: it reads the session's secure store + fixtures and returns a decision.
|
|
12
|
+
// Recording a freshly generated value (evidence + redaction) is the runner's job, via the
|
|
13
|
+
// `record:true` flag on a generator decision.
|
|
14
|
+
import { resolveFixtureValue } from '../fixtures/catalog.js';
|
|
15
|
+
import { generateFieldValue } from './generatedDataPolicy.js';
|
|
16
|
+
const CANONICAL_VAR = {
|
|
17
|
+
email: 'SWIPIUM_TEST_EMAIL',
|
|
18
|
+
username: 'SWIPIUM_TEST_USERNAME',
|
|
19
|
+
password: 'SWIPIUM_TEST_PASSWORD',
|
|
20
|
+
confirm_password: 'SWIPIUM_TEST_PASSWORD',
|
|
21
|
+
otp: 'SWIPIUM_TEST_OTP',
|
|
22
|
+
};
|
|
23
|
+
function generatorVarName(field) {
|
|
24
|
+
return CANONICAL_VAR[field] ?? `SWIPIUM_GEN_${field.toUpperCase()}`;
|
|
25
|
+
}
|
|
26
|
+
/** Plan the value for one field. Does not mutate the session (the runner records generated values). */
|
|
27
|
+
export function planInputForField(session, req, ctx) {
|
|
28
|
+
const { field } = req;
|
|
29
|
+
// 1. Existing secure user input for this field.
|
|
30
|
+
const canonical = CANONICAL_VAR[field];
|
|
31
|
+
if (canonical) {
|
|
32
|
+
const existing = session.inputValues.get(canonical);
|
|
33
|
+
if (existing != null) {
|
|
34
|
+
const secret = field === 'password' || field === 'confirm_password' || field === 'otp';
|
|
35
|
+
return { decision: 'secure_input', value: existing, varName: canonical, secret, source: 'secure_input', field };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// 2. Declared fixture value or generator (existing fixture catalog — may itself mutate session
|
|
39
|
+
// for fixture-declared generators, which is the intended behavior).
|
|
40
|
+
const fixture = resolveFixtureValue(session, req.label, req.locator?.value, { role: req.field });
|
|
41
|
+
if (fixture) {
|
|
42
|
+
return { decision: 'fixture', value: fixture.value, varName: fixture.varName, secret: fixture.secret, source: 'fixture', generator: fixture.generator, field };
|
|
43
|
+
}
|
|
44
|
+
// OTP is never invented — only a real provider or a secure input may supply it.
|
|
45
|
+
if (field === 'otp') {
|
|
46
|
+
return { decision: 'needs_input', kind: 'otp_or_manual_verification', reason: 'a one-time code is required and cannot be generated', field };
|
|
47
|
+
}
|
|
48
|
+
// 3. Built-in safe generator, gated on the generated-account decision + policy field opt-ins.
|
|
49
|
+
if (ctx.generationAllowed) {
|
|
50
|
+
const gen = generateFieldValue(field, ctx.policy, { timestamp: ctx.timestamp, index: ctx.index });
|
|
51
|
+
if (gen) {
|
|
52
|
+
return { decision: 'generator', value: gen.value, varName: generatorVarName(field), secret: gen.secret, source: 'generator', generator: gen.generator, record: true, field };
|
|
53
|
+
}
|
|
54
|
+
// generation allowed but this field is not safely generatable (phone/dob without opt-in).
|
|
55
|
+
if (req.required) {
|
|
56
|
+
return { decision: 'needs_input', kind: 'create_test_data', reason: `field "${req.label ?? field}" cannot be safely generated under the current policy`, field };
|
|
57
|
+
}
|
|
58
|
+
return { decision: 'skip', reason: `optional field "${req.label ?? field}" left blank (not safely generatable)`, field };
|
|
59
|
+
}
|
|
60
|
+
// 4 / 5. No safe value available.
|
|
61
|
+
if (req.required) {
|
|
62
|
+
const kind = field === 'email' || field === 'username' || field === 'password' || field === 'confirm_password' ? 'credentials' : 'create_test_data';
|
|
63
|
+
return { decision: 'needs_input', kind, reason: `required field "${req.label ?? field}" has no safe value and generation is not allowed here`, field };
|
|
64
|
+
}
|
|
65
|
+
return { decision: 'skip', reason: `optional field "${req.label ?? field}" skipped — no value source and generation not allowed`, field };
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=inputPlanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputPlanner.js","sourceRoot":"","sources":["../../src/firstRun/inputPlanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// SWIPIUM-REQ-02 — onboarding progression. Prefer non-destructive forward/skip controls
|
|
2
|
+
// (Next / Continue / Skip / Get started / Done) and never tap a destructive or unknown control.
|
|
3
|
+
// PURE: returns the single best forward action (or none) for a classified onboarding screen.
|
|
4
|
+
import { classifyRisk } from '../explore/policy.js';
|
|
5
|
+
// Forward controls, ranked: an explicit "skip" finishes onboarding fastest; otherwise advance.
|
|
6
|
+
const FORWARD_RANKED = [
|
|
7
|
+
{ re: /\b(skip)\b/i, rank: 5, why: 'skip onboarding' },
|
|
8
|
+
{ re: /\b(get\s+started|let'?s\s+go|start)\b/i, rank: 4, why: 'start using the app' },
|
|
9
|
+
{ re: /\b(done|finish|complete)\b/i, rank: 4, why: 'finish onboarding' },
|
|
10
|
+
{ re: /\b(continue)\b/i, rank: 3, why: 'continue onboarding' },
|
|
11
|
+
{ re: /\b(next)\b/i, rank: 2, why: 'advance to the next onboarding step' },
|
|
12
|
+
{ re: /\b(maybe\s+later|not\s+now|no\s+thanks)\b/i, rank: 1, why: 'dismiss an optional onboarding prompt' },
|
|
13
|
+
];
|
|
14
|
+
/** Pick the safest forward control on an onboarding screen. */
|
|
15
|
+
export function planOnboardingStep(elements) {
|
|
16
|
+
let best;
|
|
17
|
+
for (const el of elements) {
|
|
18
|
+
if (!el.clickable)
|
|
19
|
+
continue;
|
|
20
|
+
const hay = `${el.label ?? ''} ${el.text ?? ''} ${el.id ?? ''}`;
|
|
21
|
+
const match = FORWARD_RANKED.find((f) => f.re.test(hay));
|
|
22
|
+
if (!match)
|
|
23
|
+
continue;
|
|
24
|
+
// Never advance via something the risk classifier flags as destructive.
|
|
25
|
+
if (classifyRisk({ label: el.label ?? el.text, id: el.id, role: el.role }).risk === 'destructive')
|
|
26
|
+
continue;
|
|
27
|
+
if (!best || match.rank > best.rank)
|
|
28
|
+
best = { el, rank: match.rank, why: match.why };
|
|
29
|
+
}
|
|
30
|
+
if (!best) {
|
|
31
|
+
return { blockedReason: 'no safe forward/skip control found on the onboarding screen' };
|
|
32
|
+
}
|
|
33
|
+
const el = best.el;
|
|
34
|
+
return {
|
|
35
|
+
action: {
|
|
36
|
+
type: 'tap',
|
|
37
|
+
targetRef: el.ref,
|
|
38
|
+
label: el.label ?? el.text,
|
|
39
|
+
locator: { strategy: el.id ? 'id' : el.label ? 'accessibility' : 'text', value: el.id ?? el.label ?? el.text },
|
|
40
|
+
bounds: el.bounds,
|
|
41
|
+
reason: best.why,
|
|
42
|
+
risk: 'safe',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=onboardingStateMachine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboardingStateMachine.js","sourceRoot":"","sources":["../../src/firstRun/onboardingStateMachine.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,gGAAgG;AAChG,6FAA6F;AAG7F,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,+FAA+F;AAC/F,MAAM,cAAc,GAAqD;IACvE,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,iBAAiB,EAAE;IACtD,EAAE,EAAE,EAAE,wCAAwC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,qBAAqB,EAAE;IACrF,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE;IACxE,EAAE,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,qBAAqB,EAAE;IAC9D,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,qCAAqC,EAAE;IAC1E,EAAE,EAAE,EAAE,4CAA4C,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,uCAAuC,EAAE;CAC5G,CAAC;AAOF,+DAA+D;AAC/D,MAAM,UAAU,kBAAkB,CAAC,QAA2B;IAC5D,IAAI,IAAoE,CAAC;IACzE,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC,EAAE,CAAC,SAAS;YAAE,SAAS;QAC5B,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;QAChE,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,wEAAwE;QACxE,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,aAAa;YAAE,SAAS;QAC5G,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI;YAAE,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;IACvF,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,aAAa,EAAE,6DAA6D,EAAE,CAAC;IAC1F,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IACnB,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,EAAE,CAAC,GAAG;YACjB,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI;YAC1B,OAAO,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE;YAC9G,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,MAAM,EAAE,IAAI,CAAC,GAAG;YAChB,IAAI,EAAE,MAAM;SACb;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// SWIPIUM-REQ-02 — paywall policy. Swipium NEVER purchases. It records paywall coverage and only
|
|
2
|
+
// closes/skips when there is a clearly safe visible dismiss/restore/skip path. PURE.
|
|
3
|
+
// Controls that buy / subscribe — must never be auto-tapped.
|
|
4
|
+
const PURCHASE = /\b(subscribe|buy|purchase|start\s+(free\s+)?trial|upgrade|continue\s+to\s+payment|pay|unlock\s+premium|get\s+premium|choose\s+plan|select\s+plan)\b/i;
|
|
5
|
+
// Safe ways off a paywall.
|
|
6
|
+
const SAFE_DISMISS = [
|
|
7
|
+
{ re: /\b(skip)\b/i, rank: 4, why: 'skip the paywall' },
|
|
8
|
+
{ re: /\b(not\s+now|maybe\s+later|no\s+thanks|dismiss)\b/i, rank: 4, why: 'dismiss the paywall' },
|
|
9
|
+
{ re: /\b(close|✕|×|x)\b/i, rank: 3, why: 'close the paywall' },
|
|
10
|
+
{ re: /\b(continue\s+(with\s+)?free|free\s+version|stay\s+free|use\s+free)\b/i, rank: 3, why: 'continue on the free tier' },
|
|
11
|
+
{ re: /\b(restore\s+purchase[s]?)\b/i, rank: 1, why: 'restore purchases (non-destructive)' },
|
|
12
|
+
];
|
|
13
|
+
// Android/iOS close-affordances by id/accessibility.
|
|
14
|
+
const CLOSE_ID = /(^|[:/])(close|btn_close|dismiss|cancel|x_button|close_button|nav_close)\b/i;
|
|
15
|
+
function isPurchase(el) {
|
|
16
|
+
return PURCHASE.test(`${el.label ?? ''} ${el.text ?? ''} ${el.id ?? ''}`);
|
|
17
|
+
}
|
|
18
|
+
/** Decide how to handle a classified paywall. Never returns a purchase action. */
|
|
19
|
+
export function planPaywall(elements) {
|
|
20
|
+
let best;
|
|
21
|
+
for (const el of elements) {
|
|
22
|
+
if (!el.clickable)
|
|
23
|
+
continue;
|
|
24
|
+
if (isPurchase(el))
|
|
25
|
+
continue; // never buy
|
|
26
|
+
const hay = `${el.label ?? ''} ${el.text ?? ''}`;
|
|
27
|
+
let match = SAFE_DISMISS.find((d) => d.re.test(hay));
|
|
28
|
+
if (!match && CLOSE_ID.test(el.id ?? ''))
|
|
29
|
+
match = { re: CLOSE_ID, rank: 3, why: 'close the paywall (close affordance)' };
|
|
30
|
+
if (!match)
|
|
31
|
+
continue;
|
|
32
|
+
if (!best || match.rank > best.rank)
|
|
33
|
+
best = { el, rank: match.rank, why: match.why };
|
|
34
|
+
}
|
|
35
|
+
const coverage = 'paywall encountered — recorded coverage; no purchase attempted';
|
|
36
|
+
if (!best) {
|
|
37
|
+
return { coverage, stop: true };
|
|
38
|
+
}
|
|
39
|
+
const el = best.el;
|
|
40
|
+
return {
|
|
41
|
+
coverage,
|
|
42
|
+
stop: false,
|
|
43
|
+
action: {
|
|
44
|
+
type: best.rank >= 4 ? 'skip' : 'tap',
|
|
45
|
+
targetRef: el.ref,
|
|
46
|
+
label: el.label ?? el.text,
|
|
47
|
+
locator: { strategy: el.id ? 'id' : el.label ? 'accessibility' : 'text', value: el.id ?? el.label ?? el.text },
|
|
48
|
+
bounds: el.bounds,
|
|
49
|
+
reason: best.why,
|
|
50
|
+
risk: 'safe',
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=paywallPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paywallPolicy.js","sourceRoot":"","sources":["../../src/firstRun/paywallPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// SWIPIUM-REQ-02 — shared types for the first-run smoke / auth / onboarding / safe-test-data lane.
|
|
2
|
+
// These describe the data exchanged between the screen classifier, the input planner, the auth /
|
|
3
|
+
// onboarding / paywall state machines, and the firstRunPlanner. They are intentionally
|
|
4
|
+
// backend-neutral (no Driver references) so the planning layer stays pure + unit-testable; the
|
|
5
|
+
// driver loop in firstRunRunner.ts is the only part that touches a real device.
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/firstRun/types.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,iGAAiG;AACjG,uFAAuF;AACvF,+FAA+F;AAC/F,gFAAgF"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const GENERATORS = {
|
|
2
|
+
email: () => `swipium.qa.${Date.now()}@example.test`,
|
|
3
|
+
person_name: () => 'Swipium QA User',
|
|
4
|
+
number: () => '42',
|
|
5
|
+
text: () => 'Swipium test value',
|
|
6
|
+
city: () => 'Test City',
|
|
7
|
+
country: () => 'Testland',
|
|
8
|
+
color: () => 'Blue',
|
|
9
|
+
phone: () => '+15550101000',
|
|
10
|
+
date: () => '2026-01-15',
|
|
11
|
+
};
|
|
12
|
+
const GENERATOR_ALIASES = {
|
|
13
|
+
email: 'email',
|
|
14
|
+
email_address: 'email',
|
|
15
|
+
person: 'person_name',
|
|
16
|
+
person_name: 'person_name',
|
|
17
|
+
full_name: 'person_name',
|
|
18
|
+
display_name: 'person_name',
|
|
19
|
+
number: 'number',
|
|
20
|
+
numeric: 'number',
|
|
21
|
+
text: 'text',
|
|
22
|
+
city: 'city',
|
|
23
|
+
city_name: 'city',
|
|
24
|
+
country: 'country',
|
|
25
|
+
country_name: 'country',
|
|
26
|
+
color: 'color',
|
|
27
|
+
phone: 'phone',
|
|
28
|
+
phone_number: 'phone',
|
|
29
|
+
mobile: 'phone',
|
|
30
|
+
date: 'date',
|
|
31
|
+
date_iso: 'date',
|
|
32
|
+
};
|
|
33
|
+
const FIELD_HINTS = [
|
|
34
|
+
{ field: 'email', re: /\b(email|user(name)?|login|account)\b/i },
|
|
35
|
+
{ field: 'password', re: /\b(pass(word)?|secret)\b/i },
|
|
36
|
+
{ field: 'otp', re: /\b(otp|code|2fa|mfa)\b/i },
|
|
37
|
+
{ field: 'display_name', re: /\b(display\s*name|full\s*name|name)\b/i },
|
|
38
|
+
{ field: 'first_name', re: /\b(first\s*name|given\s*name)\b/i },
|
|
39
|
+
{ field: 'last_name', re: /\b(last\s*name|family\s*name|surname)\b/i },
|
|
40
|
+
{ field: 'city', re: /\bcity\b/i },
|
|
41
|
+
{ field: 'country', re: /\bcountry\b/i },
|
|
42
|
+
{ field: 'phone', re: /\b(phone|mobile|tel)\b/i },
|
|
43
|
+
{ field: 'date', re: /\b(date|birthday|dob)\b/i },
|
|
44
|
+
{ field: 'search', re: /\b(search|query|find|filter)\b/i },
|
|
45
|
+
];
|
|
46
|
+
function variableName(fixture, field) {
|
|
47
|
+
return `SWIPIUM_${fixture}_${field}`.toUpperCase().replace(/[^A-Z0-9]+/g, '_');
|
|
48
|
+
}
|
|
49
|
+
function fixtureFields(f) {
|
|
50
|
+
if (!f.fields || typeof f.fields !== 'object')
|
|
51
|
+
return {};
|
|
52
|
+
return f.fields;
|
|
53
|
+
}
|
|
54
|
+
function normalizeText(value) {
|
|
55
|
+
return (value ?? '').toLowerCase().replace(/[_-]+/g, ' ').replace(/[^a-z0-9]+/g, ' ').replace(/\s+/g, ' ').trim();
|
|
56
|
+
}
|
|
57
|
+
function normalizeGenerator(value) {
|
|
58
|
+
if (!value)
|
|
59
|
+
return undefined;
|
|
60
|
+
return GENERATOR_ALIASES[value.trim().toLowerCase().replace(/[-\s]+/g, '_')];
|
|
61
|
+
}
|
|
62
|
+
function fieldScore(fieldName, spec, key, context = {}) {
|
|
63
|
+
const normalizedField = normalizeText(fieldName);
|
|
64
|
+
const tokens = normalizedField.split(' ').filter(Boolean);
|
|
65
|
+
let score = normalizedField && key.includes(normalizedField) ? 30 : 0;
|
|
66
|
+
if (!score && tokens.length > 1 && tokens.every((token) => key.includes(token)))
|
|
67
|
+
score += 20;
|
|
68
|
+
const hint = FIELD_HINTS.find((h) => h.field === fieldName || h.re.test(fieldName));
|
|
69
|
+
if (hint?.re.test(key))
|
|
70
|
+
score += 50;
|
|
71
|
+
if (spec.role) {
|
|
72
|
+
const role = normalizeText(context.role);
|
|
73
|
+
const wanted = normalizeText(spec.role);
|
|
74
|
+
if (wanted && ((role && (role.includes(wanted) || wanted.includes(role))) || key.includes(wanted)))
|
|
75
|
+
score += 35;
|
|
76
|
+
}
|
|
77
|
+
if (spec.inputType) {
|
|
78
|
+
const wanted = normalizeText(spec.inputType);
|
|
79
|
+
const inputType = normalizeText(context.inputType);
|
|
80
|
+
const role = normalizeText(context.role);
|
|
81
|
+
if (wanted && (inputType.includes(wanted) || role.includes(wanted) || key.includes(wanted)))
|
|
82
|
+
score += 45;
|
|
83
|
+
const typeHint = FIELD_HINTS.find((h) => h.field === wanted || h.re.test(wanted));
|
|
84
|
+
if (typeHint?.re.test(key))
|
|
85
|
+
score += 35;
|
|
86
|
+
}
|
|
87
|
+
if (normalizeGenerator(spec.generator) && hint?.re.test(key))
|
|
88
|
+
score += 10;
|
|
89
|
+
return score;
|
|
90
|
+
}
|
|
91
|
+
export function resolveFixtureValue(session, label, locatorValue, context = {}) {
|
|
92
|
+
const key = normalizeText(`${label ?? ''} ${locatorValue ?? ''} ${context.placeholder ?? ''} ${context.nearbyText ?? ''} ${context.role ?? ''} ${context.inputType ?? ''}`);
|
|
93
|
+
let best;
|
|
94
|
+
for (const fixture of session.fixtures) {
|
|
95
|
+
for (const field of Object.keys(fixtureFields(fixture))) {
|
|
96
|
+
const score = fieldScore(field, fixtureFields(fixture)[field], key, context);
|
|
97
|
+
if (score > (best?.score ?? 0))
|
|
98
|
+
best = { fixture, field, score };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (best && best.score > 0) {
|
|
102
|
+
const spec = fixtureFields(best.fixture)[best.field];
|
|
103
|
+
const varName = spec.var ?? variableName(best.fixture.name, best.field);
|
|
104
|
+
const secret = !!spec.secret || /pass|secret|token|otp|pin|cvv|key/i.test(best.field);
|
|
105
|
+
const generated = session.generatedValues.find((g) => g.varName === varName && g.fixture === best.fixture.name && g.field === best.field);
|
|
106
|
+
if (generated) {
|
|
107
|
+
session.inputValues.set(varName, generated.value);
|
|
108
|
+
return { value: generated.value, varName, secret: generated.secret, fixture: best.fixture.name, field: best.field, source: 'generator', generator: generated.generator };
|
|
109
|
+
}
|
|
110
|
+
const fromVar = session.inputValues.get(varName) ?? (spec.var ? process.env[spec.var] : undefined);
|
|
111
|
+
if (fromVar != null)
|
|
112
|
+
return { value: fromVar, varName, secret, fixture: best.fixture.name, field: best.field, source: 'variable' };
|
|
113
|
+
if (spec.value != null)
|
|
114
|
+
return { value: spec.value, varName, secret, fixture: best.fixture.name, field: best.field, source: 'value' };
|
|
115
|
+
const generator = normalizeGenerator(spec.generator);
|
|
116
|
+
if (generator && GENERATORS[generator]) {
|
|
117
|
+
const value = GENERATORS[generator]();
|
|
118
|
+
session.inputValues.set(varName, value);
|
|
119
|
+
session.generatedValues.push({ at: Date.now(), fixture: best.fixture.name, field: best.field, varName, generator, value, secret: false });
|
|
120
|
+
return { value, varName, secret: false, fixture: best.fixture.name, field: best.field, source: 'generator', generator };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const legacy = key ? session.fixtures.find((f) => f.value && (key.includes(normalizeText(f.name)) || normalizeText(f.name).includes(key))) : undefined;
|
|
124
|
+
if (legacy?.value)
|
|
125
|
+
return { value: legacy.value, varName: variableName(legacy.name, 'value'), secret: false, fixture: legacy.name, field: 'value', source: 'legacy_value' };
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
export function hasDisposableState(session) {
|
|
129
|
+
return session.fixtures.some((f) => f.disposable === true || f.environment === 'test');
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/fixtures/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Shared flow discovery: list .swipium/flows/*.yaml|*.yml. Used by qa_plan (names → candidate
|
|
2
|
+
// workflows) and qa_smoke (paths → run the pack). One source so the two never disagree.
|
|
3
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
4
|
+
import { join, basename } from 'node:path';
|
|
5
|
+
export function listFlowFiles(root) {
|
|
6
|
+
const dir = join(root, '.swipium', 'flows');
|
|
7
|
+
if (!existsSync(dir))
|
|
8
|
+
return [];
|
|
9
|
+
try {
|
|
10
|
+
return readdirSync(dir)
|
|
11
|
+
.filter((f) => /\.ya?ml$/i.test(f))
|
|
12
|
+
.map((f) => ({ name: basename(f).replace(/\.ya?ml$/i, ''), path: join(dir, f) }));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/flows/discover.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,wFAAwF;AAExF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAO3C,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,GAAG,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|