@odavl/guardian 0.1.0-rc1 → 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/CHANGELOG.md +146 -0
- package/README.md +155 -97
- package/bin/guardian.js +1544 -55
- package/config/README.md +59 -0
- package/config/profiles/landing-demo.yaml +16 -0
- package/package.json +26 -11
- package/policies/landing-demo.json +22 -0
- package/src/enterprise/audit-logger.js +166 -0
- package/src/enterprise/pdf-exporter.js +267 -0
- package/src/enterprise/rbac-gate.js +142 -0
- package/src/enterprise/rbac.js +239 -0
- package/src/enterprise/site-manager.js +180 -0
- package/src/founder/feedback-system.js +156 -0
- package/src/founder/founder-tracker.js +213 -0
- package/src/founder/usage-signals.js +141 -0
- package/src/guardian/alert-ledger.js +121 -0
- package/src/guardian/attempt-engine.js +587 -12
- package/src/guardian/attempt-registry.js +42 -1
- package/src/guardian/attempt-relevance.js +106 -0
- package/src/guardian/attempt.js +85 -39
- package/src/guardian/attempts-filter.js +63 -0
- package/src/guardian/baseline.js +50 -8
- package/src/guardian/breakage-intelligence.js +1 -0
- package/src/guardian/browser-pool.js +131 -0
- package/src/guardian/browser.js +28 -1
- package/src/guardian/ci-cli.js +121 -0
- package/src/guardian/ci-mode.js +15 -0
- package/src/guardian/ci-output.js +38 -0
- package/src/guardian/cli-summary.js +167 -67
- package/src/guardian/config-loader.js +162 -0
- package/src/guardian/data-guardian-detector.js +189 -0
- package/src/guardian/detection-layers.js +271 -0
- package/src/guardian/drift-detector.js +100 -0
- package/src/guardian/enhanced-html-reporter.js +221 -4
- package/src/guardian/env-guard.js +127 -0
- package/src/guardian/failure-intelligence.js +173 -0
- package/src/guardian/first-run-profile.js +89 -0
- package/src/guardian/first-run.js +54 -0
- package/src/guardian/flag-validator.js +111 -0
- package/src/guardian/flow-executor.js +309 -44
- package/src/guardian/html-reporter.js +2 -0
- package/src/guardian/human-reporter.js +431 -0
- package/src/guardian/index.js +22 -19
- package/src/guardian/init-command.js +9 -5
- package/src/guardian/intent-detector.js +146 -0
- package/src/guardian/journey-definitions.js +132 -0
- package/src/guardian/journey-scan-cli.js +145 -0
- package/src/guardian/journey-scanner.js +583 -0
- package/src/guardian/junit-reporter.js +18 -1
- package/src/guardian/language-detection.js +99 -0
- package/src/guardian/live-cli.js +95 -0
- package/src/guardian/live-scheduler-runner.js +137 -0
- package/src/guardian/live-scheduler.js +146 -0
- package/src/guardian/market-reporter.js +357 -82
- package/src/guardian/parallel-executor.js +116 -0
- package/src/guardian/pattern-analyzer.js +348 -0
- package/src/guardian/policy.js +80 -3
- package/src/guardian/prerequisite-checker.js +101 -0
- package/src/guardian/preset-loader.js +27 -18
- package/src/guardian/profile-loader.js +96 -0
- package/src/guardian/reality.js +1612 -115
- package/src/guardian/reporter.js +27 -41
- package/src/guardian/run-artifacts.js +212 -0
- package/src/guardian/run-cleanup.js +207 -0
- package/src/guardian/run-latest.js +90 -0
- package/src/guardian/run-list.js +211 -0
- package/src/guardian/run-summary.js +20 -0
- package/src/guardian/scan-presets.js +100 -11
- package/src/guardian/selector-fallbacks.js +394 -0
- package/src/guardian/semantic-contact-detection.js +255 -0
- package/src/guardian/semantic-contact-finder.js +201 -0
- package/src/guardian/semantic-targets.js +234 -0
- package/src/guardian/site-introspection.js +257 -0
- package/src/guardian/smoke.js +258 -0
- package/src/guardian/snapshot-schema.js +25 -1
- package/src/guardian/snapshot.js +69 -3
- package/src/guardian/stability-scorer.js +169 -0
- package/src/guardian/success-evaluator.js +214 -0
- package/src/guardian/template-command.js +184 -0
- package/src/guardian/text-formatters.js +426 -0
- package/src/guardian/timeout-profiles.js +57 -0
- package/src/guardian/verdict.js +320 -0
- package/src/guardian/verdicts.js +74 -0
- package/src/guardian/wait-for-outcome.js +120 -0
- package/src/guardian/watch-runner.js +181 -0
- package/src/payments/stripe-checkout.js +169 -0
- package/src/plans/plan-definitions.js +148 -0
- package/src/plans/plan-manager.js +211 -0
- package/src/plans/usage-tracker.js +210 -0
- package/src/recipes/recipe-engine.js +188 -0
- package/src/recipes/recipe-failure-analysis.js +159 -0
- package/src/recipes/recipe-registry.js +134 -0
- package/src/recipes/recipe-runtime.js +507 -0
- package/src/recipes/recipe-store.js +410 -0
- package/guardian-contract-v1.md +0 -149
- /package/{guardian.config.json → config/guardian.config.json} +0 -0
- /package/{guardian.policy.json → config/guardian.policy.json} +0 -0
- /package/{guardian.profile.docs.yaml → config/profiles/docs.yaml} +0 -0
- /package/{guardian.profile.ecommerce.yaml → config/profiles/ecommerce.yaml} +0 -0
- /package/{guardian.profile.marketing.yaml → config/profiles/marketing.yaml} +0 -0
- /package/{guardian.profile.saas.yaml → config/profiles/saas.yaml} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const PROFILE_PATH = path.join(__dirname, '../../data/guardian-profiles.json');
|
|
5
|
+
let cachedProfiles = null;
|
|
6
|
+
let cachedMtime = null;
|
|
7
|
+
|
|
8
|
+
function normalizeOrigin(value) {
|
|
9
|
+
if (!value) return null;
|
|
10
|
+
try {
|
|
11
|
+
const url = value.startsWith('http://') || value.startsWith('https://')
|
|
12
|
+
? new URL(value)
|
|
13
|
+
: new URL(`http://${value}`);
|
|
14
|
+
return url.origin;
|
|
15
|
+
} catch (err) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function loadProfilesFile() {
|
|
21
|
+
try {
|
|
22
|
+
if (!fs.existsSync(PROFILE_PATH)) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
const stat = fs.statSync(PROFILE_PATH);
|
|
26
|
+
if (cachedProfiles && cachedMtime === stat.mtimeMs) {
|
|
27
|
+
return cachedProfiles;
|
|
28
|
+
}
|
|
29
|
+
const raw = fs.readFileSync(PROFILE_PATH, 'utf8');
|
|
30
|
+
const data = JSON.parse(raw);
|
|
31
|
+
const profiles = [];
|
|
32
|
+
|
|
33
|
+
if (Array.isArray(data)) {
|
|
34
|
+
data.forEach((entry) => {
|
|
35
|
+
const origin = normalizeOrigin(entry.origin || entry.site);
|
|
36
|
+
if (!origin || !entry.selectors) return;
|
|
37
|
+
profiles.push({ site: origin, selectors: entry.selectors, navigation: entry.navigation });
|
|
38
|
+
});
|
|
39
|
+
} else if (data && typeof data === 'object') {
|
|
40
|
+
Object.keys(data).forEach((key) => {
|
|
41
|
+
const origin = normalizeOrigin(key);
|
|
42
|
+
if (!origin) return;
|
|
43
|
+
const entry = data[key];
|
|
44
|
+
if (!entry || typeof entry !== 'object') return;
|
|
45
|
+
profiles.push({ site: origin, selectors: entry.selectors || entry, navigation: entry.navigation });
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
cachedProfiles = profiles;
|
|
50
|
+
cachedMtime = stat.mtimeMs;
|
|
51
|
+
return profiles;
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.log(`⚠️ Failed to load profiles: ${err.message}`);
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveProfileForUrl(url) {
|
|
59
|
+
if (!url) return null;
|
|
60
|
+
let origin = null;
|
|
61
|
+
let host = null;
|
|
62
|
+
try {
|
|
63
|
+
const u = new URL(url);
|
|
64
|
+
origin = u.origin;
|
|
65
|
+
host = u.hostname;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const profiles = loadProfilesFile();
|
|
71
|
+
if (profiles.length === 0) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const exact = profiles.find((p) => p.site === origin);
|
|
76
|
+
if (exact) return exact;
|
|
77
|
+
|
|
78
|
+
const hostMatch = profiles.find((p) => {
|
|
79
|
+
try {
|
|
80
|
+
const u = new URL(p.site);
|
|
81
|
+
if (u.port && u.port !== '80') {
|
|
82
|
+
return u.hostname === host && u.port === (new URL(origin)).port;
|
|
83
|
+
}
|
|
84
|
+
return u.hostname === host;
|
|
85
|
+
} catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return hostMatch || null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = {
|
|
94
|
+
resolveProfileForUrl,
|
|
95
|
+
loadProfilesFile,
|
|
96
|
+
};
|