diff --git a/PALO_AssessmentPath.html b/PALO_AssessmentPath.html index ef775aa..9348520 100644 --- a/PALO_AssessmentPath.html +++ b/PALO_AssessmentPath.html @@ -32,12 +32,10 @@ @@ -70,7 +68,6 @@

Five linked governance gates

05

Evidence bundle

Export the route, readiness, sources, and disclaimer.

Built on the PALO Assessment Path.

-
Optional monitoring companion. After deployment, use PolicyWatcher to follow public privacy-policy and terms-of-service changes that may affect the operating context. Keep the original source and human review in the PALO evidence record.
@@ -85,25 +82,6 @@

Classify the case and build the route

-
-
-

External monitoring companion | local receiver

-

PolicyWatcher monitoring signal

-

Import a structured observation locally. PALO preserves the complete signal and flags Measure and Prove for accountable review; confidence does not determine legal significance or control effectiveness.

-
-
- - - Signal schema -
- -
No signal imported. PolicyWatcher remains separate from PALO and no case data is sent to the portal.
-
The synthetic agentic invoice case is ready to load.
@@ -208,6 +186,33 @@

Local validation receipt

+
+ + Optional after-deployment monitoring signal + Import a PolicyWatcher observation only when the core case route is ready. + +
+
+

External monitoring companion | local receiver

+

PolicyWatcher monitoring signal

+

Import a structured observation locally. PALO preserves the complete signal and flags Measure and Prove for accountable review; confidence does not determine legal significance or control effectiveness.

+

Optional companion. After deployment, PolicyWatcher can follow public privacy-policy and terms-of-service changes that may affect the operating context. Keep the original source and human review in the PALO evidence record.

+
+
+ + + Signal schema +
+ +
No signal imported. PolicyWatcher remains separate from PALO and no case data is sent to the portal.
+
+
+
Use the route as a starting point. The export includes PALO version, route logic, evidence readiness, official source links, and a plain-language disclaimer so the next reviewer can see what was assessed and what remains open.
diff --git a/PALO_Guide.html b/PALO_Guide.html new file mode 100644 index 0000000..dbd56b2 --- /dev/null +++ b/PALO_Guide.html @@ -0,0 +1,375 @@ + + + + + + PALO Guide | Find the Next Accountable Step + + + + + + + + + + + + + + + + + + + + Skip to main content + + + +
+
+
+
+

PALO Guide | Deterministic local workbench

+

Understand PALO. Find the next accountable step.

+

Describe the governance situation, see which signals changed the route, and leave with concrete artifacts and a bounded product integration pattern.

+ +
+ +
+
+ +
+
+ +

Browser-local and source-grounded. This guide does not send answers, make legal decisions, certify compliance or authorize deployment. Answers remain in this tab unless you explicitly choose device storage.

+
+
+ +
+
+
+

Guided workbench

+

Turn six signals into a traceable route.

+

Change an answer and run the route again. The rules are local and deterministic, so the same inputs produce the same recommendation.

+
+ +
+ + +
+
+
+ Route output +

Recommendation

+
+ Local inference +
+

Ready for your inputs.

+ +
+ 01-06 +

Start with the situation, not a module name.

+

The route will show a starting phase, two to four PALO steps, expected evidence and an MCP integration class.

+
+ + + + +
+
+
+
+ +
+
+
+
+

How PALO reasons

+

Six phases, one evidence thread.

+
+

The governance loop is canonical. The recommendation selects a proportionate entry point; it does not skip accountable review or turn framework guidance into authority.

+
+
    +
  1. 01Frame

    Define purpose, scope, owners and affected people.

    Artifact: use-case brief
  2. +
  3. 02Classify

    Establish the risk route and level of scrutiny.

    Artifact: risk route
  4. +
  5. 03Assess

    Evaluate impacts, authority, autonomy and oversight.

    Artifact: impact record
  6. +
  7. 04Control

    Assign owned, testable safeguards and gates.

    Artifact: control plan
  8. +
  9. 05Measure

    Set indicators, thresholds, owners and cadence.

    Artifact: KPI/KRI register
  10. +
  11. 06Prove & Review

    Assemble evidence and decide what must reopen.

    Artifact: evidence bundle
  12. +
+
+ Evidence is not authority by implication. +

Canonical definitions structure the work. Source-backed context still needs applicability review. Local previews are not operational evidence. Human-review-required signals cannot change governance state on their own.

+
+
+
+ +
+
+
+
+

Integrate PALO into your product

+

Guide first. Protect actions separately.

+
+

The three guide tools explain and plan. They do not authorize deployment or execute protected actions. Add the PALO-AI governed path only when a product can cause effects.

+
+ +
+
+
+ Product edge + Client, product or workflow + Authenticated by the product +
+ +
+ PALO guide tools + Explain, infer, plan + Read-oriented governance guidance +
+ +
+ Released sources + Semantic, gate and control registries + Versioned definitions and boundaries +
+
+
+ When actions need protection +
Action claimPALO-AI governed pathProtected executor and verified effect
+ The developer-preview runtime is not a production authorization boundary. Use isolated, non-consequential tools until readiness gaps are closed. +
+
+ +
+
palo_explain_framework

Explain phases, artifacts, boundaries and released framework concepts.

+
palo_infer_governance_route

Return a deterministic, reasoned route from declared context signals.

+
palo_plan_product_integration

Recommend a bounded integration class, architecture and readiness cautions.

+
+

Read the PALO Guide Agent and MCP integration manual for the prompt contract, tool inputs, response boundaries and product-side implementation checklist.

+ +
+
+
+
Local development

MCP over stdio

+ +
+
{
+  "mcpServers": {
+    "palo": {
+      "command": "node",
+      "args": ["/path/to/PALO/packages/palo-mcp-server/index.js"]
+    }
+  }
+}
+

Use an absolute path and isolated development data. The reference package remains a Developer Preview.

+
+
+
+
Remote preview

Authenticated Streamable HTTP

+ +
+
{
+  "type": "streamable-http",
+  "url": "https://your-palo-host.example/mcp",
+  "headers": {
+    "Authorization": "Bearer ${PALO_MCP_TOKEN}"
+  }
+}
+

Keep tokens in the client's secret store, require TLS, minimize exposed tools and configure the server host allowlist.

+
+
+

Configuration examples are ready to copy.

+
+ Production boundary check +

Product identity, tenant scope, tool allowlists, credential custody, unavoidable enforcement, durable execution, reviewer authentication, monitoring and independent security assurance remain product-side and deployment responsibilities.

+ Review the production-readiness route +
+
+
+ +
+ +
+
+ + + + diff --git a/README.md b/README.md index 6205421..32e2c7d 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ ### [Run the preloaded Evidence Pack case](https://paloframework.org/PALO_AssessmentPath.html?sample=agentic-invoice#assessment-form) +### [Ask PALO and find an accountable route](https://paloframework.org/PALO_Guide.html) + No account. No mandatory telemetry. Your answers stay in the browser and export is voluntary. The receipt proves local schema checks and digest binding; it is not certification, legal advice, production approval or independent assurance. From a clone: diff --git a/assets/palo-assessment-path.js b/assets/palo-assessment-path.js index 11ba6ea..f83522c 100644 --- a/assets/palo-assessment-path.js +++ b/assets/palo-assessment-path.js @@ -277,6 +277,8 @@ signalInput.addEventListener("change", function () { var file = signalInput.files[0]; if (!file) return; + var signalDisclosure = signalInput.closest("details"); + if (signalDisclosure) signalDisclosure.open = true; signalStatus.classList.remove("is-error", "is-pending"); signalStatus.innerHTML = "Validating locally. " + esc(file.name) + " is not being uploaded."; document.documentElement.removeAttribute("data-policywatcher-import"); diff --git a/assets/palo-guide.css b/assets/palo-guide.css new file mode 100644 index 0000000..6d15ab6 --- /dev/null +++ b/assets/palo-guide.css @@ -0,0 +1,1176 @@ +.palo-guide-page { + min-width: 0; + overflow-x: hidden; + color: var(--palo-ink); + background: var(--palo-white); +} + +.palo-guide-page main { + min-width: 0; +} + +.palo-guide-hero { + padding: clamp(64px, 8vw, 112px) 0 72px; + background: var(--palo-surface); + border-bottom: 1px solid var(--palo-line); +} + +.palo-guide-hero-grid { + display: grid; + grid-template-columns: minmax(0, 1.13fr) minmax(330px, .87fr); + gap: clamp(42px, 8vw, 104px); + align-items: center; +} + +.palo-guide-hero h1 { + max-width: 850px; + margin: 0; + font-size: clamp(3rem, 6.5vw, 6.3rem); + line-height: .98; + letter-spacing: -.045em; +} + +.palo-guide-hero-lead { + max-width: 740px; + margin: 24px 0 0; + color: var(--palo-ink-soft); + font-size: clamp(1.08rem, 1.7vw, 1.3rem); + line-height: 1.55; +} + +.palo-guide-trace { + min-width: 0; + padding: 26px 28px 28px; + background: var(--palo-white); + border: 1px solid var(--palo-line); + border-top: 5px solid var(--palo-gold); + box-shadow: 16px 18px 0 #dfe8ec; +} + +.palo-guide-trace ol { + margin: 0; + padding: 0; + list-style: none; +} + +.palo-guide-trace li { + display: grid; + grid-template-columns: 68px minmax(0, 1fr); + gap: 16px; + padding: 20px 0; + border-top: 1px solid var(--palo-line); +} + +.palo-guide-trace li:first-child { + border-top-color: var(--palo-teal); +} + +.palo-guide-trace li span { + color: var(--palo-teal); + font: 800 .68rem/1.4 ui-monospace, SFMono-Regular, Consolas, monospace; + letter-spacing: .06em; + text-transform: uppercase; +} + +.palo-guide-trace li strong { + font-size: .94rem; + line-height: 1.45; +} + +.palo-guide-trust { + color: var(--palo-white); + background: var(--palo-ink); + border-bottom: 3px solid var(--palo-gold); +} + +.palo-guide-trust .palo-shell { + display: flex; + align-items: flex-start; + gap: 12px; + padding-top: 16px; + padding-bottom: 16px; +} + +.palo-guide-trust .palo-svg-icon { + flex: 0 0 auto; + margin-top: 3px; + color: #8edadd; +} + +.palo-guide-trust p { + margin: 0; + color: #d9e7ee; + font-size: .9rem; +} + +.palo-guide-trust strong { + color: var(--palo-white); +} + +.palo-guide-section { + padding: clamp(62px, 8vw, 104px) 0; + border-bottom: 1px solid var(--palo-line); +} + +.palo-guide-section-head { + max-width: 880px; + margin-bottom: 38px; +} + +.palo-guide-section-head h2 { + margin: 0; + font-size: clamp(2rem, 4vw, 3.65rem); + line-height: 1.04; + letter-spacing: -.025em; +} + +.palo-guide-section-head > p:last-child, +.palo-guide-section-head-split > p { + margin: 18px 0 0; + color: var(--palo-muted); + font-size: 1.02rem; +} + +.palo-guide-section-head-split { + display: grid; + grid-template-columns: minmax(0, 1.18fr) minmax(290px, .82fr); + gap: 52px; + max-width: none; + align-items: end; +} + +.palo-guide-section-head-split > p { + margin: 0 0 4px; + padding-left: 22px; + border-left: 3px solid var(--palo-gold); +} + +.palo-guide-workbench-section { + background: var(--palo-white); +} + +.palo-guide-workbench { + display: grid; + grid-template-columns: minmax(300px, 360px) minmax(0, 1fr); + min-width: 0; + border: 1px solid #bcccdc; + background: var(--palo-white); + box-shadow: 0 20px 50px rgba(16, 42, 67, .09); +} + +.palo-guide-input-rail { + min-width: 0; + background: var(--palo-surface); + border-right: 1px solid #bcccdc; +} + +.palo-guide-rail-head, +.palo-guide-result-head { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + min-height: 84px; + padding: 20px 24px; + border-bottom: 1px solid #bcccdc; +} + +.palo-guide-rail-head { + color: var(--palo-white); + background: var(--palo-teal-dark); +} + +.palo-guide-rail-head span, +.palo-guide-result-head span:first-child { + display: block; + color: #9ed7da; + font: 800 .66rem/1.4 ui-monospace, SFMono-Regular, Consolas, monospace; + letter-spacing: .08em; + text-transform: uppercase; +} + +.palo-guide-rail-head strong, +.palo-guide-result-head h3 { + display: block; + margin: 4px 0 0; + color: inherit; + font-size: 1.15rem; + line-height: 1.2; +} + +.palo-guide-form { + padding: 10px 24px 26px; +} + +.palo-guide-field { + padding: 17px 0; + border-bottom: 1px solid var(--palo-line); +} + +.palo-guide-field label { + display: flex; + align-items: baseline; + gap: 9px; + margin-bottom: 8px; + color: var(--palo-ink); + font-size: .88rem; + font-weight: 800; +} + +.palo-guide-field label > span { + color: var(--palo-gold-ink); + font: 800 .68rem/1.4 ui-monospace, SFMono-Regular, Consolas, monospace; +} + +.palo-guide-field label small { + margin-left: auto; + color: var(--palo-muted); + font-size: .68rem; + font-weight: 700; + text-transform: uppercase; +} + +.palo-guide-field select, +.palo-guide-field input[type="text"] { + width: 100%; + min-height: 48px; + padding: 10px 12px; + color: var(--palo-ink); + background: var(--palo-white); + border: 1px solid #829ab1; + border-radius: 4px; + font: inherit; + font-size: .92rem; +} + +.palo-guide-field select:invalid { + color: var(--palo-muted); +} + +.palo-guide-save { + display: flex; + align-items: flex-start; + gap: 11px; + min-height: 58px; + margin: 18px 0 0; + padding: 10px 0; + color: var(--palo-ink-soft); + cursor: pointer; +} + +.palo-guide-save input { + flex: 0 0 auto; + width: 20px; + height: 20px; + margin: 2px 0 0; + accent-color: var(--palo-teal); +} + +.palo-guide-save strong, +.palo-guide-save small { + display: block; +} + +.palo-guide-save strong { + color: var(--palo-ink); + font-size: .86rem; +} + +.palo-guide-save small { + margin-top: 3px; + font-size: .74rem; + line-height: 1.35; +} + +.palo-guide-form-actions { + display: grid; + gap: 10px; + margin-top: 16px; +} + +.palo-guide-form-actions .palo-btn { + width: 100%; + white-space: normal; +} + +.palo-guide-result { + min-width: 0; + padding-bottom: 32px; +} + +.palo-guide-result-head { + min-height: 84px; +} + +.palo-guide-result-head span:first-child { + color: var(--palo-teal); +} + +.palo-guide-local-badge { + padding: 5px 8px; + color: var(--palo-teal-dark); + background: var(--palo-teal-light); + border: 1px solid #a9d8da; + border-radius: 3px; + font: 800 .65rem/1.3 ui-monospace, SFMono-Regular, Consolas, monospace; + letter-spacing: .05em; + text-transform: uppercase; +} + +.palo-guide-live-status { + margin: 0; + padding: 10px 28px; + color: var(--palo-muted); + background: #fbfcfd; + border-bottom: 1px solid var(--palo-line); + font-size: .78rem; +} + +.palo-guide-state { + max-width: 660px; + margin: clamp(46px, 9vw, 118px) auto; + padding: 0 32px; + text-align: center; +} + +.palo-guide-state-index { + display: inline-block; + color: var(--palo-gold-ink); + font: 800 .72rem/1.4 ui-monospace, SFMono-Regular, Consolas, monospace; + letter-spacing: .08em; + text-transform: uppercase; +} + +.palo-guide-state h4 { + margin: 13px 0 10px; + color: var(--palo-ink); + font-size: clamp(1.45rem, 3vw, 2.2rem); + line-height: 1.15; +} + +.palo-guide-state p { + margin: 0; + color: var(--palo-muted); +} + +.palo-guide-error { + padding: 24px; + background: #fff5f5; + border-left: 4px solid var(--palo-red); + text-align: left; +} + +.palo-guide-populated { + min-width: 0; + padding: 28px; +} + +.palo-guide-decision-strip { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + border: 1px solid var(--palo-line); + border-top: 5px solid var(--palo-gold); +} + +.palo-guide-decision-strip > div { + min-width: 0; + padding: 20px; +} + +.palo-guide-decision-strip > div + div { + border-left: 1px solid var(--palo-line); +} + +.palo-guide-decision-strip span, +.palo-guide-because > span { + display: block; + color: var(--palo-teal); + font: 800 .66rem/1.4 ui-monospace, SFMono-Regular, Consolas, monospace; + letter-spacing: .08em; + text-transform: uppercase; +} + +.palo-guide-decision-strip strong { + display: block; + margin-top: 8px; + color: var(--palo-ink); + font-size: clamp(1.15rem, 2.4vw, 1.65rem); + line-height: 1.15; + overflow-wrap: anywhere; +} + +.palo-guide-because { + display: grid; + grid-template-columns: 76px minmax(0, 1fr); + gap: 14px; + margin-top: 18px; + padding: 17px 18px; + color: var(--palo-ink-soft); + background: #fffaf0; + border-left: 4px solid var(--palo-gold); +} + +.palo-guide-because > span { + color: var(--palo-gold-ink); +} + +.palo-guide-because p { + margin: 0; +} + +.palo-guide-result-block { + min-width: 0; + margin-top: 30px; +} + +.palo-guide-result-block h4 { + margin: 0 0 12px; + color: var(--palo-ink); + font-size: .8rem; + letter-spacing: .08em; + text-transform: uppercase; +} + +.palo-guide-route { + margin: 0; + padding: 0; + list-style: none; + border-top: 1px solid #bcccdc; +} + +.palo-guide-route li { + display: grid; + grid-template-columns: 48px minmax(0, 1fr) minmax(150px, .35fr); + gap: 15px; + min-width: 0; + padding: 18px 0; + border-bottom: 1px solid var(--palo-line); +} + +.palo-guide-route-number { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + color: var(--palo-white); + background: var(--palo-teal-dark); + font: 800 .72rem/1 ui-monospace, SFMono-Regular, Consolas, monospace; +} + +.palo-guide-route strong, +.palo-guide-route p, +.palo-guide-route small { + display: block; +} + +.palo-guide-route strong { + color: var(--palo-ink); +} + +.palo-guide-route p { + margin: 5px 0 0; + color: var(--palo-muted); + font-size: .88rem; + line-height: 1.5; +} + +.palo-guide-route small { + color: var(--palo-gold-ink); + font-size: .74rem; + font-weight: 800; + line-height: 1.45; +} + +.palo-guide-result-split { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 20px; +} + +.palo-guide-signals { + display: flex; + flex-wrap: wrap; + gap: 7px; + margin: 0; + padding: 0; + list-style: none; +} + +.palo-guide-signals li { + padding: 6px 8px; + color: var(--palo-ink-soft); + background: var(--palo-surface); + border: 1px solid var(--palo-line); + border-radius: 3px; + font-size: .72rem; + font-weight: 800; +} + +.palo-guide-boundary-block { + padding: 16px 18px; + background: var(--palo-ink); +} + +.palo-guide-boundary-block h4 { + color: #8edadd; +} + +.palo-guide-boundary-block p { + margin: 0; + color: #d9e7ee; + font-size: .84rem; +} + +.palo-guide-handoffs { + display: flex; + flex-wrap: wrap; + gap: 9px; +} + +.palo-guide-handoffs a { + display: inline-flex; + align-items: center; + min-height: 44px; + padding: 9px 12px; + color: var(--palo-teal-dark) !important; + background: var(--palo-white); + border: 1px solid var(--palo-teal-dark); + border-radius: 4px; + font-size: .82rem; + font-weight: 800; + text-decoration: none; +} + +.palo-guide-handoffs a:hover { + color: var(--palo-white) !important; + background: var(--palo-teal-dark); +} + +.palo-guide-reasoning { + background: var(--palo-surface); +} + +.palo-guide-phase-line { + display: grid; + grid-template-columns: repeat(6, minmax(0, 1fr)); + margin: 0; + padding: 0; + border-top: 1px solid #829ab1; + border-left: 1px solid #829ab1; + list-style: none; +} + +.palo-guide-phase-line li { + min-width: 0; + min-height: 250px; + padding: 20px 17px; + background: var(--palo-white); + border-right: 1px solid #829ab1; + border-bottom: 1px solid #829ab1; +} + +.palo-guide-phase-line li:nth-child(3), +.palo-guide-phase-line li:nth-child(6) { + border-top: 4px solid var(--palo-teal); + padding-top: 16px; +} + +.palo-guide-phase-line li:nth-child(6) { + border-top-color: var(--palo-gold); +} + +.palo-guide-phase-line span, +.palo-guide-phase-line strong, +.palo-guide-phase-line small { + display: block; +} + +.palo-guide-phase-line span { + color: var(--palo-gold-ink); + font: 800 .7rem/1.4 ui-monospace, SFMono-Regular, Consolas, monospace; +} + +.palo-guide-phase-line strong { + margin-top: 32px; + font-size: 1.02rem; + line-height: 1.2; +} + +.palo-guide-phase-line p { + margin: 11px 0; + color: var(--palo-muted); + font-size: .82rem; + line-height: 1.45; +} + +.palo-guide-phase-line small { + color: var(--palo-teal-dark); + font-size: .7rem; + font-weight: 800; + line-height: 1.4; +} + +.palo-guide-authority-note { + display: grid; + grid-template-columns: minmax(190px, .4fr) minmax(0, 1.6fr); + gap: 26px; + margin-top: 24px; + padding: 24px; + color: var(--palo-white); + background: var(--palo-ink); + border-left: 5px solid var(--palo-gold); +} + +.palo-guide-authority-note p { + margin: 0; + color: #d9e7ee; +} + +.palo-guide-integration { + background: var(--palo-white); +} + +.palo-guide-architecture { + padding: 24px; + background: var(--palo-surface); + border: 1px solid #bcccdc; +} + +.palo-guide-architecture-main { + display: grid; + grid-template-columns: minmax(0, 1fr) 34px minmax(0, 1.2fr) 34px minmax(0, 1.2fr); + gap: 10px; + align-items: center; +} + +.palo-guide-architecture-main article { + min-width: 0; + min-height: 142px; + padding: 20px; + background: var(--palo-white); + border: 1px solid #9fb3c8; +} + +.palo-guide-architecture-main article.is-guide-tools { + color: var(--palo-white); + background: var(--palo-teal-dark); + border-color: var(--palo-teal-dark); + border-top: 4px solid var(--palo-gold); + padding-top: 17px; +} + +.palo-guide-architecture-main > i, +.palo-guide-architecture-protected i { + color: var(--palo-gold-ink); + font-style: normal; + font-size: 1.45rem; + font-weight: 800; + text-align: center; +} + +.palo-guide-architecture-main span, +.palo-guide-architecture-main strong, +.palo-guide-architecture-main small { + display: block; +} + +.palo-guide-architecture-main span { + color: var(--palo-teal); + font-size: .66rem; + font-weight: 800; + letter-spacing: .08em; + text-transform: uppercase; +} + +.palo-guide-architecture-main strong { + margin-top: 13px; + color: inherit; + line-height: 1.25; +} + +.palo-guide-architecture-main small { + margin-top: 13px; + color: var(--palo-muted); + line-height: 1.4; +} + +.palo-guide-architecture-main .is-guide-tools span, +.palo-guide-architecture-main .is-guide-tools small { + color: #a8dadd; +} + +.palo-guide-architecture-protected { + margin-top: 20px; + padding: 18px 20px; + background: #fffaf0; + border-left: 4px solid var(--palo-gold); +} + +.palo-guide-architecture-protected > span { + display: block; + margin-bottom: 10px; + color: var(--palo-gold-ink); + font-size: .68rem; + font-weight: 800; + letter-spacing: .08em; + text-transform: uppercase; +} + +.palo-guide-architecture-protected > div { + display: grid; + grid-template-columns: minmax(0, 1fr) 32px minmax(0, 1.25fr) 32px minmax(0, 1.4fr); + gap: 8px; + align-items: center; +} + +.palo-guide-architecture-protected > small { + display: block; + margin-top: 12px; + color: var(--palo-muted); + line-height: 1.45; +} + +.palo-guide-tool-ledger { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + margin-top: 24px; + border-top: 1px solid #bcccdc; + border-left: 1px solid #bcccdc; +} + +.palo-guide-tool-ledger article { + min-width: 0; + padding: 20px; + border-right: 1px solid #bcccdc; + border-bottom: 1px solid #bcccdc; +} + +.palo-guide-tool-ledger code { + color: var(--palo-teal-dark); + font: 800 .79rem/1.5 ui-monospace, SFMono-Regular, Consolas, monospace; + overflow-wrap: anywhere; +} + +.palo-guide-tool-ledger p { + margin: 10px 0 0; + color: var(--palo-muted); + font-size: .86rem; +} + +.palo-guide-agent-manual { + margin: 16px 0 0; + padding: 14px 18px; + color: var(--palo-ink-soft); + background: #edf8f8; + border-left: 4px solid var(--palo-teal); +} + +.palo-guide-agent-manual a { + display: inline-flex; + align-items: center; + min-height: 44px; + font-weight: 800; +} + +.palo-guide-config-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 20px; + margin-top: 24px; +} + +.palo-guide-config { + min-width: 0; + border: 1px solid #bcccdc; + background: var(--palo-white); +} + +.palo-guide-config-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; + min-height: 82px; + padding: 16px 18px; +} + +.palo-guide-config-head span { + color: var(--palo-teal); + font-size: .66rem; + font-weight: 800; + letter-spacing: .08em; + text-transform: uppercase; +} + +.palo-guide-config-head h3 { + margin: 3px 0 0; + font-size: 1.12rem; +} + +.palo-guide-copy { + flex: 0 0 auto; + min-width: 72px; + min-height: 44px; + padding: 8px 12px; + color: var(--palo-teal-dark); + background: var(--palo-white); + border: 1px solid var(--palo-teal-dark); + border-radius: 4px; + font: inherit; + font-size: .8rem; + font-weight: 800; + cursor: pointer; +} + +.palo-guide-copy:hover { + color: var(--palo-white); + background: var(--palo-teal-dark); +} + +.palo-guide-config pre { + min-width: 0; + min-height: 230px; + margin: 0; + padding: 20px; + overflow: auto; + color: #e9f3f5; + background: var(--palo-ink); + font: .78rem/1.6 ui-monospace, SFMono-Regular, Consolas, monospace; + white-space: pre-wrap; + overflow-wrap: anywhere; +} + +.palo-guide-config > p { + margin: 0; + padding: 16px 18px; + color: var(--palo-muted); + font-size: .82rem; +} + +.palo-guide-copy-status { + margin: 12px 0 0; + color: var(--palo-muted); + font-size: .8rem; +} + +.palo-guide-integration-caution { + display: grid; + grid-template-columns: 200px minmax(0, 1fr) auto; + gap: 24px; + align-items: center; + margin-top: 28px; + padding: 22px 24px; + color: var(--palo-white); + background: var(--palo-ink); + border-top: 4px solid var(--palo-gold); +} + +.palo-guide-integration-caution p { + margin: 0; + color: #d9e7ee; + font-size: .86rem; +} + +.palo-guide-integration-caution a { + display: inline-flex; + align-items: center; + min-height: 44px; + color: #a8e2e5 !important; + font-size: .82rem; + font-weight: 800; +} + +.palo-guide-handoff-section { + background: var(--palo-surface); +} + +.palo-guide-handoff-ledger { + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + border-top: 1px solid #9fb3c8; + border-left: 1px solid #9fb3c8; +} + +.palo-guide-handoff-ledger a { + display: flex; + flex-direction: column; + min-width: 0; + min-height: 220px; + padding: 22px; + color: var(--palo-ink) !important; + background: var(--palo-white); + border-right: 1px solid #9fb3c8; + border-bottom: 1px solid #9fb3c8; + text-decoration: none; +} + +.palo-guide-handoff-ledger a:hover { + background: #edf8f8; +} + +.palo-guide-handoff-ledger span { + color: var(--palo-teal); + font-size: .68rem; + font-weight: 800; + letter-spacing: .06em; + text-transform: uppercase; +} + +.palo-guide-handoff-ledger strong { + margin-top: auto; + padding-top: 30px; + font-size: 1.04rem; +} + +.palo-guide-handoff-ledger small { + margin-top: 9px; + color: var(--palo-muted); + line-height: 1.45; +} + +@media (max-width: 1100px) { + .palo-guide-hero-grid { + grid-template-columns: minmax(0, 1fr) minmax(300px, .8fr); + gap: 48px; + } + + .palo-guide-workbench { + grid-template-columns: minmax(280px, 330px) minmax(0, 1fr); + } + + .palo-guide-phase-line { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .palo-guide-phase-line li { + min-height: 210px; + } + + .palo-guide-handoff-ledger { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .palo-guide-integration-caution { + grid-template-columns: minmax(170px, .35fr) minmax(0, 1fr); + } + + .palo-guide-integration-caution a { + grid-column: 1 / -1; + } +} + +@media (max-width: 900px) { + .palo-guide-hero-grid, + .palo-guide-section-head-split, + .palo-guide-workbench { + grid-template-columns: 1fr; + } + + .palo-guide-hero { + padding-top: 60px; + } + + .palo-guide-trace { + max-width: 620px; + } + + .palo-guide-section-head-split { + gap: 20px; + } + + .palo-guide-section-head-split > p { + margin: 0; + } + + .palo-guide-input-rail { + border-right: 0; + border-bottom: 1px solid #bcccdc; + } + + .palo-guide-form { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0 22px; + } + + .palo-guide-save, + .palo-guide-form-actions { + grid-column: 1 / -1; + } + + .palo-guide-form-actions { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .palo-guide-route li { + grid-template-columns: 48px minmax(0, 1fr); + } + + .palo-guide-route small { + grid-column: 2; + } + + .palo-guide-architecture-main { + grid-template-columns: 1fr; + } + + .palo-guide-architecture-main > i { + transform: rotate(90deg); + } + + .palo-guide-architecture-main article { + min-height: 0; + } + + .palo-guide-config-grid { + grid-template-columns: 1fr; + } + + .palo-guide-config pre { + min-height: 0; + } +} + +@media (max-width: 700px) { + .palo-guide-hero h1 { + font-size: clamp(2.7rem, 13vw, 4.5rem); + } + + .palo-guide-trace { + padding: 22px; + box-shadow: 10px 12px 0 #dfe8ec; + } + + .palo-guide-form { + display: block; + padding-left: 18px; + padding-right: 18px; + } + + .palo-guide-form-actions { + display: grid; + grid-template-columns: 1fr; + } + + .palo-guide-result-head, + .palo-guide-rail-head { + padding-left: 18px; + padding-right: 18px; + } + + .palo-guide-live-status { + padding-left: 18px; + padding-right: 18px; + } + + .palo-guide-populated { + padding: 20px 18px; + } + + .palo-guide-decision-strip, + .palo-guide-result-split, + .palo-guide-authority-note, + .palo-guide-tool-ledger, + .palo-guide-integration-caution { + grid-template-columns: 1fr; + } + + .palo-guide-decision-strip > div + div { + border-top: 1px solid var(--palo-line); + border-left: 0; + } + + .palo-guide-because { + grid-template-columns: 1fr; + gap: 7px; + } + + .palo-guide-phase-line { + grid-template-columns: 1fr; + } + + .palo-guide-phase-line li { + min-height: 0; + } + + .palo-guide-phase-line strong { + margin-top: 14px; + } + + .palo-guide-architecture { + padding: 16px; + } + + .palo-guide-architecture-protected > div { + grid-template-columns: 1fr; + text-align: center; + } + + .palo-guide-architecture-protected i { + transform: rotate(90deg); + } + + .palo-guide-tool-ledger article { + min-height: 0; + } + + .palo-guide-integration-caution { + gap: 12px; + } + + .palo-guide-handoff-ledger { + grid-template-columns: 1fr; + } + + .palo-guide-handoff-ledger a { + min-height: 160px; + } +} + +@media (max-width: 420px) { + .palo-guide-page .palo-shell { + width: min(100% - 24px, 1160px); + } + + .palo-guide-hero .palo-actions, + .palo-guide-hero .palo-btn { + width: 100%; + } + + .palo-guide-trace li { + grid-template-columns: 58px minmax(0, 1fr); + gap: 10px; + } + + .palo-guide-local-badge { + max-width: 88px; + text-align: center; + white-space: normal; + } + + .palo-guide-route li { + grid-template-columns: 40px minmax(0, 1fr); + gap: 11px; + } + + .palo-guide-route-number { + width: 36px; + height: 36px; + } + + .palo-guide-config-head { + align-items: flex-start; + } +} + +@media (prefers-reduced-motion: reduce) { + .palo-guide-page *, + .palo-guide-page *::before, + .palo-guide-page *::after { + scroll-behavior: auto !important; + animation-duration: .01ms !important; + animation-iteration-count: 1 !important; + transition-duration: .01ms !important; + } +} diff --git a/assets/palo-guide.js b/assets/palo-guide.js new file mode 100644 index 0000000..fc2a22e --- /dev/null +++ b/assets/palo-guide.js @@ -0,0 +1,454 @@ +(function () { + "use strict"; + + var STORAGE_KEY = "palo-guide-route-v3.0.1"; + var form = document.getElementById("palo-guide-form"); + if (!form) return; + + var status = document.getElementById("palo-guide-status"); + var emptyState = document.getElementById("palo-guide-empty"); + var loadingState = document.getElementById("palo-guide-loading"); + var errorState = document.getElementById("palo-guide-error"); + var populatedState = document.getElementById("palo-guide-populated"); + var startPhase = document.getElementById("palo-guide-start-phase"); + var integrationClass = document.getElementById("palo-guide-integration-class"); + var because = document.getElementById("palo-guide-because"); + var routeList = document.getElementById("palo-guide-route"); + var signalList = document.getElementById("palo-guide-signals"); + var boundary = document.getElementById("palo-guide-boundary"); + var handoffs = document.getElementById("palo-guide-handoffs"); + var resetButton = document.getElementById("palo-guide-reset"); + var saveLocal = document.getElementById("guide-save-local"); + var copyStatus = document.getElementById("palo-guide-copy-status"); + + var LABELS = { + role: { + "accountable-owner": "Accountable owner or executive", + "governance-risk": "Governance, risk or compliance", + product: "Product or service owner", + engineering: "Engineering or platform", + assurance: "Assurance or audit", + "legal-rights": "Legal or rights specialist" + }, + objective: { + orient: "Understand where to start", + classify: "Classify a use case or risk route", + "assess-impact": "Assess impacts and oversight", + "design-controls": "Design owned controls", + "measure-monitor": "Measure risk, performance or drift", + "prove-evidence": "Prepare evidence for review", + "govern-actions": "Govern tools or delegated actions", + "integrate-product": "Integrate PALO into a product" + }, + systemType: { + predictive: "Predictive or scoring model", + generative: "Generative assistant", + agentic: "Agentic system", + automation: "Workflow automation", + "third-party": "Embedded third-party AI", + unknown: "System still being defined" + }, + canAct: { + no: "Information-only system", + bounded: "Bounded tool or workflow action", + yes: "Product or system effects possible", + unknown: "Action capability undecided" + }, + impact: { + low: "Low, readily reversible impact", + moderate: "Moderate or context-dependent impact", + high: "High, consequential or hard-to-reverse impact", + unknown: "Material uncertainty" + } + }; + + var PHASES = { + frame: { + number: "01", + label: "Frame", + artifact: "Use-case brief with owner, affected people and explicit boundaries", + href: "PALO_ModelCanvasAI.html", + linkLabel: "Build the AI Model Canvas" + }, + classify: { + number: "02", + label: "Classify", + artifact: "Documented risk route with assumptions and source checks", + href: "PALO_RiskTiering.html", + linkLabel: "Open Risk Tiering" + }, + assess: { + number: "03", + label: "Assess", + artifact: "Impact, authority and oversight assessment record", + href: "PALO_FRIA.html", + linkLabel: "Start the impact assessment" + }, + control: { + number: "04", + label: "Control", + artifact: "Owned control plan with tests, gates and escalation", + href: "governance-hub/", + linkLabel: "Open Governance Hub" + }, + measure: { + number: "05", + label: "Measure", + artifact: "KPI/KRI register with thresholds, owners and cadence", + href: "PALO_KPIGenerator.html", + linkLabel: "Generate KPI and KRI" + }, + prove: { + number: "06", + label: "Prove & Review", + artifact: "Reviewable evidence bundle with open conditions and reopening triggers", + href: "PALO_AssessmentPath.html", + linkLabel: "Build the Evidence Pack" + } + }; + + var OBJECTIVE_ROUTES = { + orient: ["frame", "classify", "assess"], + classify: ["frame", "classify", "assess"], + "assess-impact": ["assess", "control", "measure"], + "design-controls": ["assess", "control", "measure", "prove"], + "measure-monitor": ["measure", "prove"], + "prove-evidence": ["prove", "frame"], + "govern-actions": ["assess", "control", "measure", "prove"], + "integrate-product": ["frame", "classify", "control", "prove"] + }; + + function valuesFromForm() { + return { + role: form.elements.role.value, + objective: form.elements.objective.value, + systemType: form.elements.systemType.value, + canAct: form.elements.canAct.value, + impact: form.elements.impact.value, + product: form.elements.product.value.trim() + }; + } + + function unique(values) { + return values.filter(function (value, index, list) { + return list.indexOf(value) === index; + }); + } + + function routeFor(input) { + var route = (OBJECTIVE_ROUTES[input.objective] || OBJECTIVE_ROUTES.orient).slice(); + var actionCapable = input.canAct === "yes" || input.canAct === "bounded" || input.systemType === "agentic"; + + if (input.objective === "integrate-product" && actionCapable) { + route = ["assess", "control", "measure", "prove"]; + } + + if (input.systemType === "unknown" && ["orient", "classify", "integrate-product"].indexOf(input.objective) !== -1) { + route.unshift("frame"); + } + + if ((input.impact === "high" || input.impact === "unknown") && input.objective === "orient") { + route = ["frame", "classify", "assess", "control"]; + } + + if (actionCapable && input.objective === "classify") { + route.push("control"); + } + + return unique(route).slice(0, 4); + } + + function integrationFor(input) { + var actionCapable = input.canAct === "yes" || input.canAct === "bounded" || input.systemType === "agentic"; + var consequential = input.impact === "high" || input.impact === "unknown"; + + if (actionCapable && consequential) { + return { + id: "workflow-admission-governed-executor", + label: "Workflow admission + governed executor", + boundary: "Use PALO guidance to shape admission criteria, then place consequential actions behind a separately authenticated, unavoidable governed-execution path with human review and verified effects. The current runtime is a Developer Preview, not a production authorization boundary." + }; + } + + if (actionCapable) { + return { + id: "governed-executor", + label: "Governed executor", + boundary: "Keep PALO guide tools read-oriented and route tool use through a separately protected executor. Bind each permitted action to explicit authority, review conditions, a receipt and effect verification. Use only isolated, non-consequential tools with the Developer Preview." + }; + } + + if (input.objective === "integrate-product" || input.impact === "moderate" || consequential) { + return { + id: "advisory-gate", + label: "Advisory gate", + boundary: "Return PALO guidance before a product transition, but leave the decision and authorization with an authenticated accountable owner. An advisory result must not silently change workflow state or be treated as a legal conclusion." + }; + } + + return { + id: "guidance-only", + label: "Guidance-only", + boundary: "Expose explanations, routes and artifact expectations as read-oriented guidance. The product must not treat the response as certification, deployment approval or a substitute for accountable legal, rights, security or assurance review." + }; + } + + function reasonForPhase(phaseId, input) { + var actionCapable = input.canAct === "yes" || input.canAct === "bounded" || input.systemType === "agentic"; + if (phaseId === "frame") { + if (input.systemType === "unknown") return "Because the system boundary is still being defined, name the intended outcome, owner, affected people and non-AI alternative before routing it."; + if (input.product) return "Because the route will be embedded in " + input.product + ", make the product boundary, users, data exchange and accountable owner explicit first."; + return "Because proportionate governance starts with a stable purpose, owner, affected people and decision boundary."; + } + if (phaseId === "classify") { + if (input.impact === "high" || input.impact === "unknown") return "Because the declared impact or uncertainty is material, record the risk route and verify current obligations against primary sources."; + return "Because system type and context determine the scrutiny, obligations and review route that follow."; + } + if (phaseId === "assess") { + if (actionCapable) return "Because the system can act or use tools, assess delegated authority, action space, autonomy, reversibility and human oversight alongside impacts."; + return "Because affected people, rights, misuse, limitations and residual uncertainty need an accountable assessment before controls are chosen."; + } + if (phaseId === "control") { + if (actionCapable) return "Because tool use creates an execution boundary, translate authority limits into owned gates, allowlists, review points, escalation and test evidence."; + return "Because identified risks only become governable when controls have owners, tests, evidence requirements and escalation paths."; + } + if (phaseId === "measure") { + return "Because accountability must remain observable, define indicators, thresholds, owners, cadence and a response when conditions change."; + } + if (input.objective === "prove-evidence") return "Because the immediate objective is review, assemble claims, sources, conditions, exceptions and reopening triggers into one reconstructable evidence record."; + return "Because the route needs a reviewable decision trail that shows what is evidenced, what remains open and who can reopen the case."; + } + + function becauseFor(input, integration) { + var parts = []; + parts.push(LABELS.objective[input.objective] + " is the immediate objective"); + if (input.canAct === "yes" || input.canAct === "bounded" || input.systemType === "agentic") parts.push("the system can create effects or use tools"); + if (input.impact === "high") parts.push("the declared impact is consequential or hard to reverse"); + if (input.impact === "unknown") parts.push("material uncertainty remains"); + if (input.systemType === "unknown") parts.push("the system boundary is not stable yet"); + if (input.product) parts.push("the route is intended for " + input.product); + return parts.join(", ") + ". These signals select " + integration.label.toLowerCase() + " while preserving a separate human authority boundary."; + } + + function signalValues(input) { + var signals = [ + LABELS.role[input.role], + LABELS.objective[input.objective], + LABELS.systemType[input.systemType], + LABELS.canAct[input.canAct], + LABELS.impact[input.impact] + ]; + if (input.product) signals.push("Target: " + input.product); + return signals; + } + + function handoffValues(input, route) { + var links = []; + route.forEach(function (phaseId) { + var phase = PHASES[phaseId]; + links.push({ href: phase.href, label: phase.linkLabel }); + }); + if (input.systemType === "agentic" || input.canAct === "yes" || input.canAct === "bounded") { + links.unshift({ href: "PALO_AgenticGovernance.html#simulator", label: "Test authority in PALO-AM" }); + } + if (input.objective === "integrate-product" || input.product) { + links.unshift({ href: "docs/palo-guide-agent-and-mcp.html", label: "Open the Guide and MCP manual" }); + } + var seen = {}; + return links.filter(function (link) { + if (seen[link.href]) return false; + seen[link.href] = true; + return true; + }).slice(0, 4); + } + + function infer(input) { + var route = routeFor(input); + var integration = integrationFor(input); + return { + startPhase: PHASES[route[0]].label, + route: route, + integration: integration, + because: becauseFor(input, integration), + signals: signalValues(input), + handoffs: handoffValues(input, route) + }; + } + + function clear(node) { + while (node.firstChild) node.removeChild(node.firstChild); + } + + function showState(name) { + emptyState.hidden = name !== "empty"; + loadingState.hidden = name !== "loading"; + errorState.hidden = name !== "error"; + populatedState.hidden = name !== "populated"; + } + + function renderRoute(input, result) { + startPhase.textContent = result.startPhase; + integrationClass.textContent = result.integration.label; + because.textContent = result.because; + boundary.textContent = result.integration.boundary; + + clear(routeList); + result.route.forEach(function (phaseId, index) { + var phase = PHASES[phaseId]; + var item = document.createElement("li"); + var number = document.createElement("span"); + var copy = document.createElement("div"); + var title = document.createElement("strong"); + var reason = document.createElement("p"); + var artifact = document.createElement("small"); + number.className = "palo-guide-route-number"; + number.textContent = String(index + 1).padStart(2, "0"); + title.textContent = phase.label; + reason.textContent = reasonForPhase(phaseId, input); + artifact.textContent = "Expected evidence: " + phase.artifact; + copy.appendChild(title); + copy.appendChild(reason); + item.appendChild(number); + item.appendChild(copy); + item.appendChild(artifact); + routeList.appendChild(item); + }); + + clear(signalList); + result.signals.forEach(function (signal) { + var item = document.createElement("li"); + item.textContent = signal; + signalList.appendChild(item); + }); + + clear(handoffs); + result.handoffs.forEach(function (handoff) { + var link = document.createElement("a"); + link.href = handoff.href; + link.textContent = handoff.label; + handoffs.appendChild(link); + }); + + showState("populated"); + status.textContent = "Route ready. " + result.route.length + " accountable steps and the " + result.integration.label + " class were selected from the declared signals."; + document.documentElement.setAttribute("data-palo-guide-route", result.integration.id); + } + + function save(input) { + if (!saveLocal.checked) { + localStorage.removeItem(STORAGE_KEY); + return; + } + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify(input)); + } catch { + saveLocal.checked = false; + status.textContent = "Route ready. Device storage was unavailable, so answers remain only in this tab."; + } + } + + function run(input, options) { + showState("loading"); + status.textContent = "Applying deterministic PALO routing rules locally."; + window.requestAnimationFrame(function () { + try { + var result = infer(input); + renderRoute(input, result); + if (!options || options.save !== false) save(input); + } catch { + showState("error"); + status.textContent = "The route could not be generated. Review the required inputs."; + document.documentElement.setAttribute("data-palo-guide-route", "error"); + } + }); + } + + function restore() { + var raw; + try { + raw = localStorage.getItem(STORAGE_KEY); + } catch { + return; + } + if (!raw) return; + try { + var saved = JSON.parse(raw); + ["role", "objective", "systemType", "canAct", "impact", "product"].forEach(function (name) { + if (form.elements[name] && typeof saved[name] === "string") form.elements[name].value = saved[name]; + }); + saveLocal.checked = true; + if (form.checkValidity()) { + run(valuesFromForm(), { save: false }); + status.textContent = "Saved device-local answers restored. Run again after making any change."; + } + } catch { + localStorage.removeItem(STORAGE_KEY); + } + } + + form.addEventListener("submit", function (event) { + event.preventDefault(); + if (!form.checkValidity()) { + showState("error"); + status.textContent = "Complete the five required signals before generating a route."; + form.reportValidity(); + return; + } + run(valuesFromForm()); + }); + + form.addEventListener("invalid", function () { + showState("error"); + status.textContent = "Complete the five required signals before generating a route."; + }, true); + + saveLocal.addEventListener("change", function () { + if (!saveLocal.checked) { + try { + localStorage.removeItem(STORAGE_KEY); + status.textContent = "Device-local answers removed. Current answers remain only in this tab."; + } catch { + status.textContent = "Device storage could not be updated in this browser context."; + } + } + }); + + resetButton.addEventListener("click", function () { + form.reset(); + try { localStorage.removeItem(STORAGE_KEY); } catch { /* Device storage is optional. */ } + clear(routeList); + clear(signalList); + clear(handoffs); + showState("empty"); + status.textContent = "Answers and any saved device-local route were cleared."; + document.documentElement.removeAttribute("data-palo-guide-route"); + form.elements.role.focus(); + }); + + document.querySelectorAll("[data-copy-target]").forEach(function (button) { + button.addEventListener("click", function () { + var target = document.getElementById(button.getAttribute("data-copy-target")); + var text = target ? target.textContent : ""; + if (!text) return; + if (!navigator.clipboard || !navigator.clipboard.writeText) { + copyStatus.textContent = "Copy is unavailable in this context. Select the configuration manually."; + return; + } + navigator.clipboard.writeText(text).then(function () { + copyStatus.textContent = "Configuration copied locally to the clipboard."; + button.textContent = "Copied"; + window.setTimeout(function () { button.textContent = "Copy"; }, 1800); + }).catch(function () { + copyStatus.textContent = "Copy is unavailable in this context. Select the configuration manually."; + }); + }); + }); + + window.__PALO_GUIDE = { + inferRoute: infer, + phases: PHASES, + storageKey: STORAGE_KEY + }; + + restore(); +}()); diff --git a/assets/palo-v21.css b/assets/palo-v21.css index 306fa71..314cea5 100644 --- a/assets/palo-v21.css +++ b/assets/palo-v21.css @@ -34,7 +34,8 @@ body.palo-v21 a:focus-visible, body.palo-v21 button:focus-visible, body.palo-v21 input:focus-visible, body.palo-v21 select:focus-visible, -body.palo-v21 textarea:focus-visible { +body.palo-v21 textarea:focus-visible, +body.palo-v21 summary:focus-visible { outline: 3px solid var(--palo-gold); outline-offset: 3px; } @@ -213,6 +214,16 @@ body.palo-v21 textarea:focus-visible { .palo-signal-review.is-error { border-left-color: var(--palo-red); } .palo-signal-review.is-pending { border-left-color: var(--palo-gold); } +.palo-signal-details { margin-top: 30px; border: 1px solid var(--palo-line); background: var(--palo-white); } +.palo-signal-details > summary { position: relative; display: flex; flex-direction: column; justify-content: center; min-height: 74px; padding: 14px 58px 14px 20px; color: var(--palo-ink); background: var(--palo-surface); cursor: pointer; list-style: none; } +.palo-signal-details > summary::-webkit-details-marker { display: none; } +.palo-signal-details > summary::after { position: absolute; top: 50%; right: 22px; content: "+"; color: var(--palo-teal); font-size: 1.4rem; font-weight: 800; line-height: 1; transform: translateY(-50%); } +.palo-signal-details[open] > summary::after { content: "-"; } +.palo-signal-details > summary span { font-weight: 800; } +.palo-signal-details > summary small { margin-top: 4px; color: var(--palo-muted); line-height: 1.4; } +.palo-signal-details .palo-signal-import { margin: 0; border: 0; border-top: 1px solid var(--palo-line); border-radius: 0; } +.palo-signal-details .palo-signal-import p + p { margin-top: 12px; } + .palo-status { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 18px; color: var(--palo-teal-dark); font-size: 0.9rem; font-weight: 800; } .palo-status .palo-svg-icon { color: var(--palo-green); } @@ -481,6 +492,15 @@ body.palo-v21 textarea:focus-visible { .palo-home-workspace-foot a { color: var(--palo-teal-dark) !important; font-weight: 800; } .palo-home-workspace-foot span:last-child { margin-left: auto; } +.palo-home-background { margin: 0; padding: 0; background: var(--palo-white); border-bottom: 1px solid var(--palo-line); } +.palo-home-background > summary { position: relative; display: flex; flex-direction: column; justify-content: center; min-height: 96px; padding: 18px max(64px, calc((100% - 1160px) / 2 + 64px)) 18px max(20px, calc((100% - 1160px) / 2)); color: var(--palo-ink); background: var(--palo-surface); cursor: pointer; list-style: none; } +.palo-home-background > summary::-webkit-details-marker { display: none; } +.palo-home-background > summary::after { position: absolute; top: 50%; right: max(24px, calc((100% - 1160px) / 2)); content: "+"; color: var(--palo-teal); font-size: 1.7rem; font-weight: 800; line-height: 1; transform: translateY(-50%); } +.palo-home-background[open] > summary::after { content: "-"; } +.palo-home-background > summary span { font-size: clamp(1.05rem, 2vw, 1.35rem); font-weight: 800; } +.palo-home-background > summary small { max-width: 780px; margin-top: 5px; color: var(--palo-muted); font-size: .82rem; line-height: 1.45; } +.palo-home-background-content { min-width: 0; } + .palo-home-footer { padding: 38px 0 26px; color: var(--palo-ink-soft); background: #f4f7f9; border-top: 1px solid var(--palo-line); } .palo-home-footer-inner { width: min(1320px, calc(100% - 40px)); margin: 0 auto; } .palo-home-footer-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 30px; } diff --git a/assets/palo-v21.js b/assets/palo-v21.js index 57bf75b..91a5944 100644 --- a/assets/palo-v21.js +++ b/assets/palo-v21.js @@ -10,7 +10,25 @@ document.head.appendChild(script); } + function revealProgressiveHashTarget() { + if (!window.location.hash || window.location.hash.length < 2) return; + var targetId; + try { targetId = decodeURIComponent(window.location.hash.slice(1)); } + catch (error) { targetId = window.location.hash.slice(1); } + var target = document.getElementById(targetId); + if (!target) return; + var disclosure = target.closest('details[data-palo-progressive-background]'); + if (!disclosure || disclosure.open) return; + disclosure.open = true; + window.requestAnimationFrame(function () { + target.scrollIntoView({ block: 'start', behavior: 'auto' }); + }); + } + function boot() { + revealProgressiveHashTarget(); + window.addEventListener('hashchange', revealProgressiveHashTarget); + document.querySelectorAll('[data-palo-menu-toggle]').forEach(function (button) { var menuId = button.getAttribute('aria-controls'); var menu = menuId ? document.getElementById(menuId) : null; diff --git a/deploy/vps/palo-ai/Caddyfile b/deploy/vps/palo-ai/Caddyfile index 1197071..1fb87b8 100644 --- a/deploy/vps/palo-ai/Caddyfile +++ b/deploy/vps/palo-ai/Caddyfile @@ -27,6 +27,16 @@ reverse_proxy palo-mcp:8788 } + handle /mcp-guide-health { + rewrite * /health + reverse_proxy palo-guide-mcp:8789 + } + + handle /mcp-guide { + rewrite * /mcp + reverse_proxy palo-guide-mcp:8789 + } + @blockedGateway { path /gateway/v1/agents/* /gateway/v1/policies/* /gateway/v1/executors/* /gateway/v1/verifiers/* /gateway/v1/approvals /gateway/v1/approvals/resolve /gateway/v1/incidents /gateway/v1/incidents/resolve /gateway/v1/evidence } diff --git a/deploy/vps/palo-ai/Dockerfile b/deploy/vps/palo-ai/Dockerfile index f2673f8..5429d1a 100644 --- a/deploy/vps/palo-ai/Dockerfile +++ b/deploy/vps/palo-ai/Dockerfile @@ -9,15 +9,16 @@ COPY package.json package-lock.json ./ RUN npm ci --omit=dev --ignore-scripts=false && npm cache clean --force COPY --chown=node:node packages/palo-mcp-server ./packages/palo-mcp-server +COPY --chown=node:node data ./data COPY --chown=node:node schemas ./schemas COPY --chown=node:node examples/policy-as-code ./examples/policy-as-code COPY --chown=root:root deploy/vps/palo-ai/docker-entrypoint.sh /usr/local/bin/palo-entrypoint RUN chmod 0755 /usr/local/bin/palo-entrypoint \ - && mkdir -p /var/lib/palo \ - && chown node:node /var/lib/palo + && mkdir -p /var/lib/palo /var/lib/palo-guide \ + && chown node:node /var/lib/palo /var/lib/palo-guide -EXPOSE 8787 8788 +EXPOSE 8787 8788 8789 ENTRYPOINT ["/usr/local/bin/palo-entrypoint"] CMD ["node", "packages/palo-mcp-server/http.js"] diff --git a/deploy/vps/palo-ai/compose.host-nginx.yaml b/deploy/vps/palo-ai/compose.host-nginx.yaml index 77f1bd0..e2a687c 100644 --- a/deploy/vps/palo-ai/compose.host-nginx.yaml +++ b/deploy/vps/palo-ai/compose.host-nginx.yaml @@ -106,16 +106,54 @@ services: retries: 5 start_period: 15s + palo-guide-mcp: + build: + context: ../../.. + dockerfile: deploy/vps/palo-ai/Dockerfile + command: ["node", "packages/palo-mcp-server/http.js"] + restart: unless-stopped + read_only: true + mem_limit: 384m + cap_drop: [ALL] + cap_add: [SETUID, SETGID] + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp:size=32m,mode=1777 + environment: + PALO_MCP_HTTP_HOST: 0.0.0.0 + PALO_MCP_HTTP_PORT: 8789 + PALO_MCP_ALLOWED_HOSTS: ${PALO_DOMAIN},127.0.0.1,localhost + PALO_MCP_EXPOSED_TOOLS: palo_explain_framework,palo_infer_governance_route,palo_plan_product_integration + PALO_MCP_HTTP_TOKEN_FILE: /run/secrets/palo_guide_mcp_token + PALO_DATA_DIR: /var/lib/palo-guide + secrets: + - palo_guide_mcp_token + volumes: + - palo_guide_data:/var/lib/palo-guide + ports: + - 127.0.0.1:18879:8789 + networks: [backend, host_access] + healthcheck: + test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:8789/health',{headers:{Host:'127.0.0.1'}}).then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"] + interval: 15s + timeout: 5s + retries: 5 + start_period: 15s + secrets: palo_gateway_token: file: ./secrets/gateway-token palo_mcp_token: file: ./secrets/mcp-token + palo_guide_mcp_token: + file: ./secrets/guide-mcp-token palo_hmac_keys: file: ./secrets/hmac-keys.json volumes: palo_data: + palo_guide_data: networks: backend: diff --git a/deploy/vps/palo-ai/compose.yaml b/deploy/vps/palo-ai/compose.yaml index 3b20f5c..e3d3d5e 100644 --- a/deploy/vps/palo-ai/compose.yaml +++ b/deploy/vps/palo-ai/compose.yaml @@ -102,6 +102,38 @@ services: retries: 5 start_period: 15s + palo-guide-mcp: + build: + context: ../../.. + dockerfile: deploy/vps/palo-ai/Dockerfile + command: ["node", "packages/palo-mcp-server/http.js"] + restart: unless-stopped + read_only: true + cap_drop: [ALL] + cap_add: [SETUID, SETGID] + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp:size=32m,mode=1777 + environment: + PALO_MCP_HTTP_HOST: 0.0.0.0 + PALO_MCP_HTTP_PORT: 8789 + PALO_MCP_ALLOWED_HOSTS: ${PALO_DOMAIN},127.0.0.1,localhost + PALO_MCP_EXPOSED_TOOLS: palo_explain_framework,palo_infer_governance_route,palo_plan_product_integration + PALO_MCP_HTTP_TOKEN_FILE: /run/secrets/palo_guide_mcp_token + PALO_DATA_DIR: /var/lib/palo-guide + secrets: + - palo_guide_mcp_token + volumes: + - palo_guide_data:/var/lib/palo-guide + networks: [backend] + healthcheck: + test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:8789/health',{headers:{Host:'127.0.0.1'}}).then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"] + interval: 15s + timeout: 5s + retries: 5 + start_period: 15s + caddy: image: ${CADDY_IMAGE:-caddy:2.11.4-alpine} restart: unless-stopped @@ -125,6 +157,8 @@ services: depends_on: palo-mcp: condition: service_healthy + palo-guide-mcp: + condition: service_healthy healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1:2019/config/"] interval: 30s @@ -136,11 +170,14 @@ secrets: file: ./secrets/gateway-token palo_mcp_token: file: ./secrets/mcp-token + palo_guide_mcp_token: + file: ./secrets/guide-mcp-token palo_hmac_keys: file: ./secrets/hmac-keys.json volumes: palo_data: + palo_guide_data: caddy_data: caddy_config: diff --git a/deploy/vps/palo-ai/nginx-governance.conf b/deploy/vps/palo-ai/nginx-governance.conf index 04a14ca..e4f44ba 100644 --- a/deploy/vps/palo-ai/nginx-governance.conf +++ b/deploy/vps/palo-ai/nginx-governance.conf @@ -24,6 +24,23 @@ server { proxy_set_header X-Forwarded-Proto $scheme; } + location = /mcp-guide-health { + proxy_pass http://127.0.0.1:18879/health; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location = /mcp-guide { + proxy_pass http://127.0.0.1:18879/mcp; + proxy_http_version 1.1; + proxy_buffering off; + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + location = /gateway/v1/approvals/resolve { return 404; } diff --git a/deploy/vps/palo-ai/setup-secrets.sh b/deploy/vps/palo-ai/setup-secrets.sh index fdb15df..fab9043 100644 --- a/deploy/vps/palo-ai/setup-secrets.sh +++ b/deploy/vps/palo-ai/setup-secrets.sh @@ -4,7 +4,7 @@ set -eu umask 077 mkdir -p secrets -for file in secrets/gateway-token secrets/mcp-token secrets/hmac-keys.json; do +for file in secrets/gateway-token secrets/mcp-token secrets/guide-mcp-token secrets/hmac-keys.json; do if [ -e "$file" ]; then echo "Refusing to overwrite existing secret: $file" >&2 exit 1 @@ -13,9 +13,10 @@ done openssl rand -hex 32 > secrets/gateway-token openssl rand -hex 32 > secrets/mcp-token +openssl rand -hex 32 > secrets/guide-mcp-token hmac_secret="$(openssl rand -hex 32)" printf '{"key-support-2026":"%s"}\n' "$hmac_secret" > secrets/hmac-keys.json unset hmac_secret -chmod 600 secrets/gateway-token secrets/mcp-token secrets/hmac-keys.json +chmod 600 secrets/gateway-token secrets/mcp-token secrets/guide-mcp-token secrets/hmac-keys.json -echo "Generated three protected secret files. Values were not printed." +echo "Generated four protected secret files. Values were not printed." diff --git a/deploy/vps/palo-ai/smoke-online.sh b/deploy/vps/palo-ai/smoke-online.sh index b968971..a84cc57 100644 --- a/deploy/vps/palo-ai/smoke-online.sh +++ b/deploy/vps/palo-ai/smoke-online.sh @@ -11,6 +11,7 @@ set -a set +a gateway_token="$(cat secrets/gateway-token)" +guide_mcp_token="$(cat secrets/guide-mcp-token)" curl --fail --silent --show-error "https://${PALO_DOMAIN}/mcp-health" printf '\n' @@ -21,8 +22,26 @@ anonymous_status="$(curl --silent --output /dev/null --write-out '%{http_code}' "https://${PALO_DOMAIN}/mcp")" test "$anonymous_status" = "401" +curl --fail --silent --show-error "https://${PALO_DOMAIN}/mcp-guide-health" +printf '\n' + +guide_anonymous_status="$(curl --silent --output /dev/null --write-out '%{http_code}' \ + -X POST -H 'Content-Type: application/json' \ + --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \ + "https://${PALO_DOMAIN}/mcp-guide")" +test "$guide_anonymous_status" = "401" + +guide_initialize="$(curl --fail --silent --show-error \ + -X POST \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json, text/event-stream' \ + -H "Authorization: Bearer $guide_mcp_token" \ + --data '{"jsonrpc":"2.0","id":2,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"palo-online-smoke","version":"1.0.0"}}}' \ + "https://${PALO_DOMAIN}/mcp-guide")" +printf '%s' "$guide_initialize" | grep -F 'serverInfo' > /dev/null + curl --fail --silent --show-error \ -H "Authorization: Bearer $gateway_token" \ "https://${PALO_DOMAIN}/gateway/v1/registry" -printf '\nOnline health, anonymous MCP rejection, and authenticated gateway checks passed.\n' -unset gateway_token +printf '\nOnline operational and guide MCP health, authentication, and gateway checks passed.\n' +unset gateway_token guide_mcp_token guide_initialize diff --git a/dist/PALO_AssessmentPath.html b/dist/PALO_AssessmentPath.html index ef775aa..9348520 100644 --- a/dist/PALO_AssessmentPath.html +++ b/dist/PALO_AssessmentPath.html @@ -32,12 +32,10 @@ @@ -70,7 +68,6 @@

Five linked governance gates

05

Evidence bundle

Export the route, readiness, sources, and disclaimer.

Built on the PALO Assessment Path.

-
Optional monitoring companion. After deployment, use PolicyWatcher to follow public privacy-policy and terms-of-service changes that may affect the operating context. Keep the original source and human review in the PALO evidence record.
@@ -85,25 +82,6 @@

Classify the case and build the route

-
-
-

External monitoring companion | local receiver

-

PolicyWatcher monitoring signal

-

Import a structured observation locally. PALO preserves the complete signal and flags Measure and Prove for accountable review; confidence does not determine legal significance or control effectiveness.

-
-
- - - Signal schema -
- -
No signal imported. PolicyWatcher remains separate from PALO and no case data is sent to the portal.
-
The synthetic agentic invoice case is ready to load.
@@ -208,6 +186,33 @@

Local validation receipt

+
+ + Optional after-deployment monitoring signal + Import a PolicyWatcher observation only when the core case route is ready. + +
+
+

External monitoring companion | local receiver

+

PolicyWatcher monitoring signal

+

Import a structured observation locally. PALO preserves the complete signal and flags Measure and Prove for accountable review; confidence does not determine legal significance or control effectiveness.

+

Optional companion. After deployment, PolicyWatcher can follow public privacy-policy and terms-of-service changes that may affect the operating context. Keep the original source and human review in the PALO evidence record.

+
+
+ + + Signal schema +
+ +
No signal imported. PolicyWatcher remains separate from PALO and no case data is sent to the portal.
+
+
+
Use the route as a starting point. The export includes PALO version, route logic, evidence readiness, official source links, and a plain-language disclaimer so the next reviewer can see what was assessed and what remains open.
diff --git a/dist/PALO_DocumentationLibrary.html b/dist/PALO_DocumentationLibrary.html index 65dead5..b6fe9ba 100644 --- a/dist/PALO_DocumentationLibrary.html +++ b/dist/PALO_DocumentationLibrary.html @@ -18,7 +18,7 @@
Choose your depth

The complete index is generated during the publication build.

-

Semantic foundation and contracts

PALO Core

Canonical v3.0.0

PALO v3.0.0 Semantic Foundation

PALO v3.0.0 introduces a versioned semantic foundation for definitions, lifecycle decisions, evidence, mappings and public exploration. It is a major contract release: machine-readable ident

Document details
reference4 mincanonical-definitionpublic-catalog
Prerequisite: No specialist prerequisiteNext: Open the Semantic Inspectordocs/palo-v3-semantic-foundation.mdOpen HTML guide

Start and adoption

PALO Core

Current Guidance

Changelog

All notable changes to the PALO Framework are documented in this file.

Document details
reference20 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation LibraryCHANGELOG.mdOpen HTML guide

PALO Core

Current Guidance

PALO activation freeze

Status: active

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/activation-freeze-2026-08.mdOpen HTML guide

PALO Core

Current Guidance

PALO case file and evidence bundle v1

v3 compatibility: the PALO v3 semantic, gate-decision and atomic evidence contracts are additive. Case File v1 and Evidence Bundle v1 remain supported; consumers may link to v3 semantic IDs

Document details
reference2 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p1-case-file-and-migration.mdOpen HTML guide

PALO Core

Current Guidance

Dependency and license inventory

Inventory date: 2026-07-12 Scope: PALO web publication and P0-P2 build/test tooling. This is an inventory aid, not legal advice or a complete software composition analysis.

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-dependency-inventory.mdOpen HTML guide

PALO Core

Current Guidance

P2 publication hygiene

Version: 1.0.0

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-publication-hygiene.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Adoption Paths

Status: audience guide for the PALO-AI v2.5 full-cycle developer preview, updated 18 July 2026.

Document details
start6 minsource-backed-contextpublic-catalog
Prerequisite: Choose an organizational role and objectiveNext: Open the guided Startdocs/palo-ai-adoption-paths.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Community and Market-Entry Plan

Status: staged communication plan for the PALO-AI v2.5 full-cycle developer preview, updated 19 July 2026.

Document details
guide5 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-community-and-market-entry.mdOpen HTML guide

PALO Core

Current Guidance

PALO platform evolution analysis

P0 establishes a minimal Node 20 toolchain for source validation, deterministic allowlisted publication, built-artifact exactness, and Chromium smoke testing. One current release identifier

Document details
reference13 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/platform-evolution-analysis.mdOpen HTML guide

PALO Core

Current Guidance

PALO Evidence Pack

Give PALO one AI use case. Leave with a traceable, reviewable evidence dossier.

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Libraryevidence-pack/README.mdOpen HTML guide

PALO Core

Current Guidance

PALO-AI n8n architecture-preview media

This folder contains the three-minute narrated developer-preview demo and its supporting script and captions.

Document details
reference1 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarymedia/README.mdOpen HTML guide

PALO Core

Current Guidance

PALO MCP reference server - Developer Preview

This package is the non-production reference implementation shipped with PALO-AI v2.5. It demonstrates the official MCP SDK over stdio and experimental bearer-authenticated Streamable HTTP,

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarypackages/palo-mcp-server/README.mdOpen HTML guide

Architecture and integration

PALO Core

Current Guidance

P2 adoption and integration index

Version: 1.0.0 Status: educational starter library; not production controls, legal advice, certification, regulatory completeness or authorization to deploy.

Document details
guide3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-adoption-integration-index.mdOpen HTML guide

PALO Core

Current Guidance

Vendor-neutral connector patterns

Version: 1.0.0 Status: architectural patterns, not configured integrations.

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-connector-patterns.mdOpen HTML guide

PALO Core

Current Guidance

P2 module contracts

Version: 1.0.0 Status: interoperability foundation; browser events are local signals, not authenticated messages or remote APIs.

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-module-contracts.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI v2.5 - Full-Cycle Agentic Assurance

Developer preview. Use synthetic or isolated data and non-consequential tools only. This implementation is not an independently assessed security boundary, compliance certification, product

Document details
reference5 minsource-backed-contextassurance-review
Prerequisite: Action Claim and Effect Contract conceptsNext: Inspect the Capability Matrixdocs/palo-ai-full-cycle-assurance.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Governance Integration Guide

Status: full-cycle developer-preview integration guide for PALO-AI v2.5, updated 18 July 2026.

Document details
guide17 minsource-backed-contextpublic-catalog
Prerequisite: One reversible tool and authority profileNext: Configure the Governance Hub technical setupdocs/palo-ai-governance-integration-guide.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI n8n Alpha Test Report

Date: 17 July 2026

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-n8n-alpha-test-report.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Governance Control Plane for n8n and Agentic Automation Platforms

Status: architecture preview updated for the PALO-AI v2.5 full-cycle developer preview. The patterns include implemented reference prototypes and future production controls; none is represen

Document details
guide7 minsource-backed-contextpublic-catalog
Prerequisite: Self-hosted n8n evaluation canvasNext: Run the governed-action demodocs/palo-ai-n8n-governance-control-plane.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI for n8n - Presentation and Launch Playbook

Status: go-to-market guide for an architecture and developer preview, not a production launch.

Document details
guide7 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-n8n-launch-playbook.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI for n8n - Three-Minute Architecture Preview Demo

Target length: three minutes.

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarymedia/palo-ai-n8n-demo-script.mdOpen HTML guide

PALO-AI

Developer Preview

n8n-nodes-palo-ai

Developer-preview PALO-AI decision gate and full-cycle outcome assurance for n8n agentic workflows.

Document details
reference4 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarypackages/n8n-nodes-palo-ai/README.mdOpen HTML guide

Operations and deployment

PALO-AI

Target Architecture

PALO-AI Cloud Reference Architecture

Status: target architecture and deployment decision record for the PALO-AI v2.5 full-cycle developer preview, updated 19 July 2026.

Document details
reference6 minsource-backed-contextpublic-catalog
Prerequisite: Threat model and deployment ownerNext: Review Production Readinessdocs/palo-ai-cloud-reference-architecture.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI n8n architecture preview - publication status

Release: 2.5 full-cycle developer preview Status: architecture source and evaluation assets published on the repository main branch; no npm publication, n8n verification request, or template

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-n8n-publication-status.mdOpen HTML guide

PALO-AI

Evaluation Deployment

PALO-AI Online VPS Deployment

Status: Internet-reachable developer-preview deployment for PALO-AI v2.5. This topology provides HTTPS and network isolation, but it does not remove the blockers tracked in the public Produc

Document details
guide8 minsource-backed-contextpublic-catalog
Prerequisite: Isolated VPS and non-production secretsNext: Run deployment validationdocs/palo-ai-vps-deployment.mdOpen HTML guide

Security and production readiness

PALO Core

Current Guidance

Security Policy

| Version | Supported | | ------- | ------------------ | | 2.5.x website and static tools | :whitecheckmark: | | 2.5.0 PALO-AI full-cycle runtime and Governance Hub | :x: developer preview;

Document details
reference4 minsource-backed-contextassurance-review
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation LibrarySECURITY.mdOpen HTML guide

PALO-AI

Planning Baseline

PALO-AI production-readiness plan

Status: remaining production-readiness plan for the v2.5 full-cycle developer preview, updated 19 July 2026. The presence of a target control or acceptance criterion below does not mean that

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: Capability MatrixNext: Open Production Readinessdocs/palo-ai-production-readiness-plan.mdOpen HTML guide

PALO-AI

Assurance Plan

PALO-AI Security Assurance and Scale Plan

Status: external-assurance plan for the PALO-AI v2.5 full-cycle developer preview, updated 19 July 2026.

Document details
reference5 minsource-backed-contextassurance-review
Prerequisite: Architecture and threat boundariesNext: Track the nine readiness gatesdocs/palo-ai-security-assurance-and-scale.mdOpen HTML guide

Governance Hub and UX

PALO-AI

Developer Preview

PALO-AI Governance Hub - GitHub copy draft

Status: ready-to-adapt English repository copy for the v2.5 developer preview, prepared 19 July 2026.

Document details
reference10 minillustrative-local-previewpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-governance-hub-github-copy.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Governance Hub - status, gaps and staged launch plan

Status: evidence-led launch plan updated 19 July 2026 for the PALO-AI v2.5 developer preview and implemented role-based GUI prototype.

Document details
guide15 minillustrative-local-previewpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-governance-hub-launch-plan.mdOpen HTML guide

PALO-AI

Prototype Specification

PALO-AI Governance Hub - Product Specification

Status: implemented interactive product prototype for the PALO-AI v2.5 developer preview, updated 19 July 2026.

Document details
reference21 minillustrative-local-previewpublic-catalog
Prerequisite: Read the Governance Hub user guideNext: Review the workflow referencedocs/palo-ai-governance-hub-product-spec.mdOpen HTML guide

PALO-AI

Current Boundary

PALO-AI Governance Hub - Delivery Status

Assessment date: 2026-08-12

Document details
reference4 minillustrative-local-previewpublic-catalog
Prerequisite: NoneNext: Open Production Readinessdocs/palo-ai-governance-hub-status.mdOpen HTML guide

PALO-AI

Interactive Prototype

PALO-AI Governance Hub - User and Interaction Guide

Status: interaction guide for the v3-aligned PALO-AI Governance Hub prototype, updated 12 August 2026.

Document details
start17 minillustrative-local-previewpublic-catalog
Prerequisite: No technical prerequisiteNext: Open the Governance Hubdocs/palo-ai-governance-hub-user-guide.mdOpen HTML guide

PALO-AI

Prototype Workflow

PALO-AI Governance Hub - Workflow and Diagram Specification

Status: design specification for a role-based GUI over the PALO-AI v2.5 developer preview.

Document details
guide12 minillustrative-local-previewpublic-catalog
Prerequisite: Governance Hub product modelNext: Test the eight-step builderdocs/palo-ai-governance-hub-workflows.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Governance Hub - website copy draft

Status: English copy deck for the implemented role-based Governance Hub prototype, updated 19 July 2026.

Document details
reference12 minillustrative-local-previewpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/site/palo-ai-governance-hub-page-copy.mdOpen HTML guide

Community and contribution

PALO Core

Current Guidance

Contributing to PALO Framework

PALO v3 semantic sources are versioned public contracts. Change the semantic source through the documented generator workflow, then run npm run semantic:generate, npm run semantic:validate a

Document details
reference4 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation LibraryCONTRIBUTING.mdOpen HTML guide

PALO Core

Current Guidance

Allowed is not verified: five-day activation window

Canonical channel: PALO GitHub Discussions

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/activation-window-2026-08.mdOpen HTML guide

PALO Core

Current Guidance

Changed because of feedback

This is the public decision log for PALO Evidence Pack activation. It records accepted, rejected and deferred findings. Participation is not endorsement, partnership, certification or approv

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/changed-because-of-feedback.mdOpen HTML guide

PALO Core

Current Guidance

PALO community channel policy

GitHub Discussions is the canonical public channel for Evidence Pack questions, reviewer findings, activation feedback and design-partner learning.

Document details
guide1 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/channel-policy.mdOpen HTML guide

PALO Core

Current Guidance

PALO founding review program

The Evidence Pack review cohort is 20 people: four reviewers in each of five communities. A person becomes a founding reviewer only after explicitly accepting the task. Public nomination alo

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/founding-review-program.mdOpen HTML guide

PALO Core

Current Guidance

n8n Community Discussion Draft

Architecture preview: a governance control plane for agent authority, policy gates, HITL and evidence in n8n

Document details
guide3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/n8n-architecture-preview-post.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI developer-preview feedback and design-partner intake

This document is the canonical, safe intake for the PALO-AI v2.5 full-cycle architecture preview. It can be used as a GitHub issue, a private form, or a facilitated interview. It is not a su

Document details
guide3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/palo-ai-feedback-design-partner-form.mdOpen HTML guide

PALO Core

Current Guidance

PALO publishes a vendor-neutral outcome-assurance adapter for Microsoft AGT

Published: 7 August 2026

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/palo-microsoft-agt-interoperability-proposal.mdOpen HTML guide

Templates and examples

PALO-AI

Current Guidance

PALO Agentic Interface (PALO-AI) - Full-Cycle Developer Preview

PALO-AI v2.5 publishes governance contracts and a non-production reference runtime for autonomous agents and agent teams. It demonstrates registered authority profiles, Action Claim 1.2, dig

Document details
guide4 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Libraryexamples/agentic-interface/README.mdOpen HTML guide

PALO Core

Current Guidance

PALO-AI v2.5 hands-on demo - permission is not correctness

This no-slides demonstration compares a direct agent tool call with full-cycle assurance over a synthetic multi-tenant catalog. It uses no production system, personal data or consequential a

Document details
guide3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Libraryexamples/hands-on-demo/README.mdOpen HTML guide

PALO Core

Current Guidance

PALO policy as code - Developer Preview

agent-delegation.rego is the draft v2.5 reference policy for canonical PALO-AI claims. It uses Rego v1 syntax and demonstrates checks for agent identity, profile state, tool and operation al

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Libraryexamples/policy-as-code/README.mdOpen HTML guide

PALO Core

Current Guidance

Board and accountable-committee review pack

Template ID: tpl-board-review Version: 1.0.0 Status: educational starter; not a board resolution, legal opinion, certification statement, or completeness claim.

Document details
guide2 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/board-review.mdOpen HTML guide

PALO Core

Current Guidance

PALO starter-library contribution

Template ID: tpl-contribution-starter Version: 1.0.0 Status: contribution starter; acceptance does not certify, endorse, or make an artifact production-ready.

Document details
guide1 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/contribution-starter.mdOpen HTML guide

PALO Core

Current Guidance

AI incident response record

Template ID: tpl-incident-response Version: 1.0.0 Status: educational starter; tailor to emergency, security, privacy, safety, employment and regulatory procedures before use.

Document details
guide1 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/incident-response.mdOpen HTML guide

PALO Core

Current Guidance

Procurement governance record

Template ID: tpl-procurement Version: 1.0.0 Status: educational starter; not legal advice, procurement approval, certification, or a production control.

Document details
guide2 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/procurement.mdOpen HTML guide

PALO Core

Current Guidance

Red-team evidence record

Template ID: tpl-red-team-evidence Version: 1.0.0 Status: educational starter; not a complete threat model, penetration test, safety evaluation, or production assurance record.

Document details
guide1 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/red-team-evidence.mdOpen HTML guide
+

Semantic foundation and contracts

PALO Core

Canonical v3.0.0

PALO v3.0.0 Semantic Foundation

PALO v3.0.0 introduces a versioned semantic foundation for definitions, lifecycle decisions, evidence, mappings and public exploration. It is a major contract release: machine-readable ident

Document details
reference4 mincanonical-definitionpublic-catalog
Prerequisite: No specialist prerequisiteNext: Open the Semantic Inspectordocs/palo-v3-semantic-foundation.mdOpen HTML guide

Start and adoption

PALO Core

Current Guidance

Changelog

All notable changes to the PALO Framework are documented in this file.

Document details
reference20 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation LibraryCHANGELOG.mdOpen HTML guide

PALO Core

Current Guidance

PALO activation freeze

Status: active

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/activation-freeze-2026-08.mdOpen HTML guide

PALO Core

Current Guidance

PALO case file and evidence bundle v1

v3 compatibility: the PALO v3 semantic, gate-decision and atomic evidence contracts are additive. Case File v1 and Evidence Bundle v1 remain supported; consumers may link to v3 semantic IDs

Document details
reference2 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p1-case-file-and-migration.mdOpen HTML guide

PALO Core

Current Guidance

Dependency and license inventory

Inventory date: 2026-07-12 Scope: PALO web publication and P0-P2 build/test tooling. This is an inventory aid, not legal advice or a complete software composition analysis.

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-dependency-inventory.mdOpen HTML guide

PALO Core

Current Guidance

P2 publication hygiene

Version: 1.0.0

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-publication-hygiene.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Adoption Paths

Status: audience guide for the PALO-AI v2.5 full-cycle developer preview, updated 18 July 2026.

Document details
start6 minsource-backed-contextpublic-catalog
Prerequisite: Choose an organizational role and objectiveNext: Open the guided Startdocs/palo-ai-adoption-paths.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Community and Market-Entry Plan

Status: staged communication plan for the PALO-AI v2.5 full-cycle developer preview, updated 19 July 2026.

Document details
guide5 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-community-and-market-entry.mdOpen HTML guide

PALO Core

Current Guidance

PALO Guide Agent and MCP Integration

Status: PALO platform v3.0.1 guide-agent contract. The guide tools are implemented as deterministic, read-only inference over released PALO registries. The protected-action runtime remains a

Document details
reference6 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-guide-agent-and-mcp.mdOpen HTML guide

PALO Core

Current Guidance

PALO platform evolution analysis

P0 establishes a minimal Node 20 toolchain for source validation, deterministic allowlisted publication, built-artifact exactness, and Chromium smoke testing. One current release identifier

Document details
reference13 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/platform-evolution-analysis.mdOpen HTML guide

PALO Core

Current Guidance

PALO Evidence Pack

Give PALO one AI use case. Leave with a traceable, reviewable evidence dossier.

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Libraryevidence-pack/README.mdOpen HTML guide

PALO Core

Current Guidance

PALO-AI n8n architecture-preview media

This folder contains the three-minute narrated developer-preview demo and its supporting script and captions.

Document details
reference1 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarymedia/README.mdOpen HTML guide

PALO Core

Current Guidance

PALO MCP reference server - Developer Preview

This package is the non-production reference implementation shipped with PALO-AI v2.5. It demonstrates the official MCP SDK over stdio and experimental bearer-authenticated Streamable HTTP,

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarypackages/palo-mcp-server/README.mdOpen HTML guide

Architecture and integration

PALO Core

Current Guidance

P2 adoption and integration index

Version: 1.0.0 Status: educational starter library; not production controls, legal advice, certification, regulatory completeness or authorization to deploy.

Document details
guide3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-adoption-integration-index.mdOpen HTML guide

PALO Core

Current Guidance

Vendor-neutral connector patterns

Version: 1.0.0 Status: architectural patterns, not configured integrations.

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-connector-patterns.mdOpen HTML guide

PALO Core

Current Guidance

P2 module contracts

Version: 1.0.0 Status: interoperability foundation; browser events are local signals, not authenticated messages or remote APIs.

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/p2-module-contracts.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI v2.5 - Full-Cycle Agentic Assurance

Developer preview. Use synthetic or isolated data and non-consequential tools only. This implementation is not an independently assessed security boundary, compliance certification, product

Document details
reference5 minsource-backed-contextassurance-review
Prerequisite: Action Claim and Effect Contract conceptsNext: Inspect the Capability Matrixdocs/palo-ai-full-cycle-assurance.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Governance Integration Guide

Status: full-cycle developer-preview integration guide for PALO-AI v2.5, updated 18 July 2026.

Document details
guide17 minsource-backed-contextpublic-catalog
Prerequisite: One reversible tool and authority profileNext: Configure the Governance Hub technical setupdocs/palo-ai-governance-integration-guide.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI n8n Alpha Test Report

Date: 17 July 2026

Document details
reference2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-n8n-alpha-test-report.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Governance Control Plane for n8n and Agentic Automation Platforms

Status: architecture preview updated for the PALO-AI v2.5 full-cycle developer preview. The patterns include implemented reference prototypes and future production controls; none is represen

Document details
guide7 minsource-backed-contextpublic-catalog
Prerequisite: Self-hosted n8n evaluation canvasNext: Run the governed-action demodocs/palo-ai-n8n-governance-control-plane.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI for n8n - Presentation and Launch Playbook

Status: go-to-market guide for an architecture and developer preview, not a production launch.

Document details
guide7 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-n8n-launch-playbook.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI for n8n - Three-Minute Architecture Preview Demo

Target length: three minutes.

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarymedia/palo-ai-n8n-demo-script.mdOpen HTML guide

PALO-AI

Developer Preview

n8n-nodes-palo-ai

Developer-preview PALO-AI decision gate and full-cycle outcome assurance for n8n agentic workflows.

Document details
reference4 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarypackages/n8n-nodes-palo-ai/README.mdOpen HTML guide

Operations and deployment

PALO-AI

Target Architecture

PALO-AI Cloud Reference Architecture

Status: target architecture and deployment decision record for the PALO-AI v2.5 full-cycle developer preview, updated 19 July 2026.

Document details
reference6 minsource-backed-contextpublic-catalog
Prerequisite: Threat model and deployment ownerNext: Review Production Readinessdocs/palo-ai-cloud-reference-architecture.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI n8n architecture preview - publication status

Release: 2.5 full-cycle developer preview Status: architecture source and evaluation assets published on the repository main branch; no npm publication, n8n verification request, or template

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-n8n-publication-status.mdOpen HTML guide

PALO-AI

Evaluation Deployment

PALO-AI Online VPS Deployment

Status: Internet-reachable developer-preview deployment for PALO-AI v2.5. This topology provides HTTPS and network isolation, but it does not remove the blockers tracked in the public Produc

Document details
guide9 minsource-backed-contextpublic-catalog
Prerequisite: Isolated VPS and non-production secretsNext: Run deployment validationdocs/palo-ai-vps-deployment.mdOpen HTML guide

Security and production readiness

PALO Core

Current Guidance

Security Policy

| Version | Supported | | ------- | ------------------ | | 2.5.x website and static tools | :whitecheckmark: | | 2.5.0 PALO-AI full-cycle runtime and Governance Hub | :x: developer preview;

Document details
reference4 minsource-backed-contextassurance-review
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation LibrarySECURITY.mdOpen HTML guide

PALO-AI

Planning Baseline

PALO-AI production-readiness plan

Status: remaining production-readiness plan for the v2.5 full-cycle developer preview, updated 19 July 2026. The presence of a target control or acceptance criterion below does not mean that

Document details
reference3 minsource-backed-contextpublic-catalog
Prerequisite: Capability MatrixNext: Open Production Readinessdocs/palo-ai-production-readiness-plan.mdOpen HTML guide

PALO-AI

Assurance Plan

PALO-AI Security Assurance and Scale Plan

Status: external-assurance plan for the PALO-AI v2.5 full-cycle developer preview, updated 19 July 2026.

Document details
reference5 minsource-backed-contextassurance-review
Prerequisite: Architecture and threat boundariesNext: Track the nine readiness gatesdocs/palo-ai-security-assurance-and-scale.mdOpen HTML guide

Governance Hub and UX

PALO-AI

Developer Preview

PALO-AI Governance Hub - GitHub copy draft

Status: ready-to-adapt English repository copy for the v2.5 developer preview, prepared 19 July 2026.

Document details
reference10 minillustrative-local-previewpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-governance-hub-github-copy.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Governance Hub - status, gaps and staged launch plan

Status: evidence-led launch plan updated 19 July 2026 for the PALO-AI v2.5 developer preview and implemented role-based GUI prototype.

Document details
guide15 minillustrative-local-previewpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/palo-ai-governance-hub-launch-plan.mdOpen HTML guide

PALO-AI

Prototype Specification

PALO-AI Governance Hub - Product Specification

Status: implemented interactive product prototype for the PALO-AI v2.5 developer preview, updated 19 July 2026.

Document details
reference21 minillustrative-local-previewpublic-catalog
Prerequisite: Read the Governance Hub user guideNext: Review the workflow referencedocs/palo-ai-governance-hub-product-spec.mdOpen HTML guide

PALO-AI

Current Boundary

PALO-AI Governance Hub - Delivery Status

Assessment date: 2026-08-12

Document details
reference4 minillustrative-local-previewpublic-catalog
Prerequisite: NoneNext: Open Production Readinessdocs/palo-ai-governance-hub-status.mdOpen HTML guide

PALO-AI

Interactive Prototype

PALO-AI Governance Hub - User and Interaction Guide

Status: interaction guide for the v3-aligned PALO-AI Governance Hub prototype, updated 12 August 2026.

Document details
start17 minillustrative-local-previewpublic-catalog
Prerequisite: No technical prerequisiteNext: Open the Governance Hubdocs/palo-ai-governance-hub-user-guide.mdOpen HTML guide

PALO-AI

Prototype Workflow

PALO-AI Governance Hub - Workflow and Diagram Specification

Status: design specification for a role-based GUI over the PALO-AI v2.5 developer preview.

Document details
guide12 minillustrative-local-previewpublic-catalog
Prerequisite: Governance Hub product modelNext: Test the eight-step builderdocs/palo-ai-governance-hub-workflows.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI Governance Hub - website copy draft

Status: English copy deck for the implemented role-based Governance Hub prototype, updated 19 July 2026.

Document details
reference12 minillustrative-local-previewpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/site/palo-ai-governance-hub-page-copy.mdOpen HTML guide

Community and contribution

PALO Core

Current Guidance

Contributing to PALO Framework

PALO v3 semantic sources are versioned public contracts. Change the semantic source through the documented generator workflow, then run npm run semantic:generate, npm run semantic:validate a

Document details
reference4 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation LibraryCONTRIBUTING.mdOpen HTML guide

PALO Core

Current Guidance

Allowed is not verified: five-day activation window

Canonical channel: PALO GitHub Discussions

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/activation-window-2026-08.mdOpen HTML guide

PALO Core

Current Guidance

Changed because of feedback

This is the public decision log for PALO Evidence Pack activation. It records accepted, rejected and deferred findings. Participation is not endorsement, partnership, certification or approv

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/changed-because-of-feedback.mdOpen HTML guide

PALO Core

Current Guidance

PALO community channel policy

GitHub Discussions is the canonical public channel for Evidence Pack questions, reviewer findings, activation feedback and design-partner learning.

Document details
guide1 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/channel-policy.mdOpen HTML guide

PALO Core

Current Guidance

PALO founding review program

The Evidence Pack review cohort is 20 people: four reviewers in each of five communities. A person becomes a founding reviewer only after explicitly accepting the task. Public nomination alo

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/founding-review-program.mdOpen HTML guide

PALO Core

Current Guidance

n8n Community Discussion Draft

Architecture preview: a governance control plane for agent authority, policy gates, HITL and evidence in n8n

Document details
guide3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/n8n-architecture-preview-post.mdOpen HTML guide

PALO-AI

Developer Preview

PALO-AI developer-preview feedback and design-partner intake

This document is the canonical, safe intake for the PALO-AI v2.5 full-cycle architecture preview. It can be used as a GitHub issue, a private form, or a facilitated interview. It is not a su

Document details
guide3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/palo-ai-feedback-design-partner-form.mdOpen HTML guide

PALO Core

Current Guidance

PALO publishes a vendor-neutral outcome-assurance adapter for Microsoft AGT

Published: 7 August 2026

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarydocs/community/palo-microsoft-agt-interoperability-proposal.mdOpen HTML guide

Templates and examples

PALO-AI

Current Guidance

PALO Agentic Interface (PALO-AI) - Full-Cycle Developer Preview

PALO-AI v2.5 publishes governance contracts and a non-production reference runtime for autonomous agents and agent teams. It demonstrates registered authority profiles, Action Claim 1.2, dig

Document details
guide4 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Libraryexamples/agentic-interface/README.mdOpen HTML guide

PALO Core

Current Guidance

PALO-AI v2.5 hands-on demo - permission is not correctness

This no-slides demonstration compares a direct agent tool call with full-cycle assurance over a synthetic multi-tenant catalog. It uses no production system, personal data or consequential a

Document details
guide3 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Libraryexamples/hands-on-demo/README.mdOpen HTML guide

PALO Core

Current Guidance

PALO policy as code - Developer Preview

agent-delegation.rego is the draft v2.5 reference policy for canonical PALO-AI claims. It uses Rego v1 syntax and demonstrates checks for agent identity, profile state, tool and operation al

Document details
guide2 minsource-backed-contextpublic-catalog
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Libraryexamples/policy-as-code/README.mdOpen HTML guide

PALO Core

Current Guidance

Board and accountable-committee review pack

Template ID: tpl-board-review Version: 1.0.0 Status: educational starter; not a board resolution, legal opinion, certification statement, or completeness claim.

Document details
guide2 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/board-review.mdOpen HTML guide

PALO Core

Current Guidance

PALO starter-library contribution

Template ID: tpl-contribution-starter Version: 1.0.0 Status: contribution starter; acceptance does not certify, endorse, or make an artifact production-ready.

Document details
guide1 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/contribution-starter.mdOpen HTML guide

PALO Core

Current Guidance

AI incident response record

Template ID: tpl-incident-response Version: 1.0.0 Status: educational starter; tailor to emergency, security, privacy, safety, employment and regulatory procedures before use.

Document details
guide1 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/incident-response.mdOpen HTML guide

PALO Core

Current Guidance

Procurement governance record

Template ID: tpl-procurement Version: 1.0.0 Status: educational starter; not legal advice, procurement approval, certification, or a production control.

Document details
guide2 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/procurement.mdOpen HTML guide

PALO Core

Current Guidance

Red-team evidence record

Template ID: tpl-red-team-evidence Version: 1.0.0 Status: educational starter; not a complete threat model, penetration test, safety evaluation, or production assurance record.

Document details
guide1 minsource-backed-contextcase-workspace
Prerequisite: No specialist prerequisite statedNext: Return to the Documentation Librarytemplates/red-team-evidence.mdOpen HTML guide

No public documents match this search.

diff --git a/dist/assets/palo-assessment-path.js b/dist/assets/palo-assessment-path.js index 11ba6ea..f83522c 100644 --- a/dist/assets/palo-assessment-path.js +++ b/dist/assets/palo-assessment-path.js @@ -277,6 +277,8 @@ signalInput.addEventListener("change", function () { var file = signalInput.files[0]; if (!file) return; + var signalDisclosure = signalInput.closest("details"); + if (signalDisclosure) signalDisclosure.open = true; signalStatus.classList.remove("is-error", "is-pending"); signalStatus.innerHTML = "Validating locally. " + esc(file.name) + " is not being uploaded."; document.documentElement.removeAttribute("data-policywatcher-import"); diff --git a/dist/assets/palo-v21.css b/dist/assets/palo-v21.css index 306fa71..314cea5 100644 --- a/dist/assets/palo-v21.css +++ b/dist/assets/palo-v21.css @@ -34,7 +34,8 @@ body.palo-v21 a:focus-visible, body.palo-v21 button:focus-visible, body.palo-v21 input:focus-visible, body.palo-v21 select:focus-visible, -body.palo-v21 textarea:focus-visible { +body.palo-v21 textarea:focus-visible, +body.palo-v21 summary:focus-visible { outline: 3px solid var(--palo-gold); outline-offset: 3px; } @@ -213,6 +214,16 @@ body.palo-v21 textarea:focus-visible { .palo-signal-review.is-error { border-left-color: var(--palo-red); } .palo-signal-review.is-pending { border-left-color: var(--palo-gold); } +.palo-signal-details { margin-top: 30px; border: 1px solid var(--palo-line); background: var(--palo-white); } +.palo-signal-details > summary { position: relative; display: flex; flex-direction: column; justify-content: center; min-height: 74px; padding: 14px 58px 14px 20px; color: var(--palo-ink); background: var(--palo-surface); cursor: pointer; list-style: none; } +.palo-signal-details > summary::-webkit-details-marker { display: none; } +.palo-signal-details > summary::after { position: absolute; top: 50%; right: 22px; content: "+"; color: var(--palo-teal); font-size: 1.4rem; font-weight: 800; line-height: 1; transform: translateY(-50%); } +.palo-signal-details[open] > summary::after { content: "-"; } +.palo-signal-details > summary span { font-weight: 800; } +.palo-signal-details > summary small { margin-top: 4px; color: var(--palo-muted); line-height: 1.4; } +.palo-signal-details .palo-signal-import { margin: 0; border: 0; border-top: 1px solid var(--palo-line); border-radius: 0; } +.palo-signal-details .palo-signal-import p + p { margin-top: 12px; } + .palo-status { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 18px; color: var(--palo-teal-dark); font-size: 0.9rem; font-weight: 800; } .palo-status .palo-svg-icon { color: var(--palo-green); } @@ -481,6 +492,15 @@ body.palo-v21 textarea:focus-visible { .palo-home-workspace-foot a { color: var(--palo-teal-dark) !important; font-weight: 800; } .palo-home-workspace-foot span:last-child { margin-left: auto; } +.palo-home-background { margin: 0; padding: 0; background: var(--palo-white); border-bottom: 1px solid var(--palo-line); } +.palo-home-background > summary { position: relative; display: flex; flex-direction: column; justify-content: center; min-height: 96px; padding: 18px max(64px, calc((100% - 1160px) / 2 + 64px)) 18px max(20px, calc((100% - 1160px) / 2)); color: var(--palo-ink); background: var(--palo-surface); cursor: pointer; list-style: none; } +.palo-home-background > summary::-webkit-details-marker { display: none; } +.palo-home-background > summary::after { position: absolute; top: 50%; right: max(24px, calc((100% - 1160px) / 2)); content: "+"; color: var(--palo-teal); font-size: 1.7rem; font-weight: 800; line-height: 1; transform: translateY(-50%); } +.palo-home-background[open] > summary::after { content: "-"; } +.palo-home-background > summary span { font-size: clamp(1.05rem, 2vw, 1.35rem); font-weight: 800; } +.palo-home-background > summary small { max-width: 780px; margin-top: 5px; color: var(--palo-muted); font-size: .82rem; line-height: 1.45; } +.palo-home-background-content { min-width: 0; } + .palo-home-footer { padding: 38px 0 26px; color: var(--palo-ink-soft); background: #f4f7f9; border-top: 1px solid var(--palo-line); } .palo-home-footer-inner { width: min(1320px, calc(100% - 40px)); margin: 0 auto; } .palo-home-footer-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 30px; } diff --git a/dist/assets/palo-v21.js b/dist/assets/palo-v21.js index 57bf75b..91a5944 100644 --- a/dist/assets/palo-v21.js +++ b/dist/assets/palo-v21.js @@ -10,7 +10,25 @@ document.head.appendChild(script); } + function revealProgressiveHashTarget() { + if (!window.location.hash || window.location.hash.length < 2) return; + var targetId; + try { targetId = decodeURIComponent(window.location.hash.slice(1)); } + catch (error) { targetId = window.location.hash.slice(1); } + var target = document.getElementById(targetId); + if (!target) return; + var disclosure = target.closest('details[data-palo-progressive-background]'); + if (!disclosure || disclosure.open) return; + disclosure.open = true; + window.requestAnimationFrame(function () { + target.scrollIntoView({ block: 'start', behavior: 'auto' }); + }); + } + function boot() { + revealProgressiveHashTarget(); + window.addEventListener('hashchange', revealProgressiveHashTarget); + document.querySelectorAll('[data-palo-menu-toggle]').forEach(function (button) { var menuId = button.getAttribute('aria-controls'); var menu = menuId ? document.getElementById(menuId) : null; diff --git a/dist/docs/palo-ai-vps-deployment.html b/dist/docs/palo-ai-vps-deployment.html index f744a7c..9a17052 100644 --- a/dist/docs/palo-ai-vps-deployment.html +++ b/dist/docs/palo-ai-vps-deployment.html @@ -24,7 +24,7 @@
-

Operations and deployment | Public documentation

PALO-AI Online VPS Deployment

LevelguideAudiencetechnicalProductPALO-AIStatusEvaluation DeploymentRead8 min

Published HTML view | Source: docs/palo-ai-vps-deployment.md

+

Operations and deployment | Public documentation

PALO-AI Online VPS Deployment

LevelguideAudiencetechnicalProductPALO-AIStatusEvaluation DeploymentRead9 min

Published HTML view | Source: docs/palo-ai-vps-deployment.md

On this page
  1. Live deployment status
  2. Address model
  3. Supplied deployment
  4. Prerequisites
  5. Configure the VPS
  6. Firewall
  7. Start the online stack
  8. Register an authority profile
  9. Verify the online endpoint
  10. Connect n8n
  11. Connect other MCP clients
  12. Public-route boundary
  13. Next implementation gates
  14. Update and rollback
  15. Backup warning
  16. Remaining production boundary

PALO-AI Online VPS Deployment#

Status: Internet-reachable developer-preview deployment for PALO-AI v2.5. This topology provides HTTPS and network isolation, but it does not remove the blockers tracked in the public Production Readiness plan.

Live deployment status#

The reference developer-preview endpoint was deployed on 17 July 2026:

@@ -44,6 +44,10 @@

Live deployment statusStreamable HTTP at /mcp, bearer-authenticated +Guide MCP transport +Prepared Streamable HTTP route at /mcp-guide, separately bearer-authenticated; deploy this release before treating it as live + + Gateway HTTPS under /gateway, bearer-authenticated and route-limited @@ -95,11 +99,21 @@

Address modelAddress modelSupplied deploymentPALO Gateway and MCP containers built from this repository;
  • HTTPS termination and redirect through existing nginx/Certbot or Caddy 2.11.4;
  • separate Docker secret files for Gateway, MCP and HMAC material;
  • +
  • a separate Guide MCP secret and allowlist containing only the three read-only guide tools;
  • persistent PALO data and Caddy certificate volumes;
  • non-root PALO containers, read-only filesystems, dropped capabilities and health checks;
  • an explicit MCP host allowlist;
  • @@ -149,6 +169,11 @@

    Configure the VPS
    bash code
    sh setup-secrets.sh

    The generated .env and secrets/ contents are ignored by Git. Back them up through a protected secret-management process; never upload or commit them.

    +

    When upgrading an existing deployment that already has the original three secret files, create only the new Guide MCP token before starting the updated Compose project:

    +
    bash code
    umask 077
    +test ! -e secrets/guide-mcp-token
    +openssl rand -hex 32 > secrets/guide-mcp-token
    +chmod 600 secrets/guide-mcp-token

    Do not rerun setup-secrets.sh over an existing deployment because it deliberately refuses to overwrite any current secret.

    Firewall#

    Preserve SSH access before enabling a firewall. A typical UFW policy is:

    bash code
    sudo ufw default deny incoming
     sudo ufw default allow outgoing
    @@ -156,7 +181,7 @@ 

    Firewall

    Do not open 8181, 8787, 8788, 18877 or 18878 publicly. The Hostinger Compose variant publishes 18877 and 18878 only on the VPS loopback interface; the clean-VPS variant keeps its administration binding on loopback as documented in its Compose file.

    +sudo ufw enable

    Do not open 8181, 8787, 8788, 8789, 18877, 18878 or 18879 publicly. The Hostinger Compose variant publishes 18877, 18878 and 18879 only on the VPS loopback interface; the clean-VPS variant keeps its administration binding on loopback as documented in its Compose file.

    Start the online stack#

    The supplied VPS currently runs nginx and Certbot for other services. On that host, use compose.host-nginx.yaml; it binds PALO only to loopback ports 18877 and 18878, leaving the existing ports and sites untouched. The generic compose.yaml with Caddy is for a clean VPS where ports 80/443 are free.

    For the existing Hostinger VPS:

    bash code
    docker compose -f compose.host-nginx.yaml config
    @@ -177,6 +202,8 @@ 

    Start the online stack
    bash code
    docker compose logs --tail=100 opa palo-gateway palo-mcp caddy

    Expected public endpoints:

    text code
    https://governance.paloframework.org/mcp-health
     https://governance.paloframework.org/mcp
    +https://governance.paloframework.org/mcp-guide-health
    +https://governance.paloframework.org/mcp-guide
     https://governance.paloframework.org/gateway/v1/registry
     https://governance.paloframework.org/gateway/v1/actions/verify

    Register an authority profile#

    Administrative registration is intentionally not exposed through the public reverse proxy. SSH into the VPS and use the loopback-only gateway. The current Hostinger deployment reads PALO_ADMIN_URL=http://127.0.0.1:18877 from .env:

    bash code
    sh register-profile.sh \
    @@ -184,8 +211,9 @@ 

    Start the online stack

    The supplied profile is development data. Before external testing, create a new versioned profile with the correct agent ID, case, tools, hosts, argument schemas, scopes and HMAC key ID.

    Verify the online endpoint#

    bash code
    sh smoke-online.sh

    This checks:

      -
    • the public MCP health endpoint over HTTPS;
    • -
    • rejection of an anonymous MCP request;
    • +
    • the operational and Guide MCP health endpoints over HTTPS;
    • +
    • rejection of anonymous operational and Guide MCP requests;
    • +
    • authenticated Guide MCP initialization;
    • authenticated access to the public Gateway registry.

    Inspect service-local health when troubleshooting:

    @@ -197,9 +225,14 @@

    Verify the online endpointConnect other MCP clients#

    For clients that support Streamable HTTP:

    text code
    Endpoint: https://governance.paloframework.org/mcp
     Authorization: Bearer <contents of secrets/mcp-token>

    Expose only the PALO-governed tools to an agent. Do not make equivalent privileged target tools available through a parallel ungoverned MCP server.

    +

    For products that only need PALO explanation, deterministic route inference and integration planning, use the separate guide-only endpoint and secrets/guide-mcp-token:

    +
    text code
    Endpoint: https://governance.paloframework.org/mcp-guide
    +Authorization: Bearer <contents of secrets/guide-mcp-token>
    +Tools: palo_explain_framework, palo_infer_governance_route, palo_plan_product_integration

    Issue a distinct secret per deployment boundary when moving beyond the single-tenant developer preview. Never place this token in public browser JavaScript.

    Public-route boundary#

    The public reverse proxy currently exposes:

    • MCP /mcp and its health endpoint; the configured remote tool allowlist remains decision/status oriented and excludes administrative and execution tools;
    • +
    • Guide MCP /mcp-guide and its health endpoint, authenticated with a separate secret and limited to three read-only guide tools;
    • Gateway health and authenticated registry read;
    • authenticated Action Claim verification and full-cycle governed execution;
    • authenticated execution detail, outcome read and explicit re-verification addressed by execution ID;
    • diff --git a/dist/docs/palo-ai-vps-deployment.md b/dist/docs/palo-ai-vps-deployment.md index e8e0f87..338b8e2 100644 --- a/dist/docs/palo-ai-vps-deployment.md +++ b/dist/docs/palo-ai-vps-deployment.md @@ -10,6 +10,7 @@ The reference developer-preview endpoint was deployed on 17 July 2026: |---|---| | Public hostname | `https://governance.paloframework.org` | | MCP transport | Streamable HTTP at `/mcp`, bearer-authenticated | +| Guide MCP transport | Prepared Streamable HTTP route at `/mcp-guide`, separately bearer-authenticated; deploy this release before treating it as live | | Gateway | HTTPS under `/gateway`, bearer-authenticated and route-limited | | Policy engine | OPA 1.17.0, Docker-internal only | | TLS | Let's Encrypt ECDSA certificate with automatic renewal | @@ -28,9 +29,12 @@ The deployment deliberately uses both private and public addresses: | `http://palo-gateway:8787` | Docker network only | Gateway behind the TLS proxy | | `http://127.0.0.1:18877` | Current VPS host only | Administrative profile registration over SSH | | `http://127.0.0.1:18878` | Current VPS host only | nginx-to-MCP proxy target | +| `http://127.0.0.1:18879` | Current VPS host only | nginx-to-guide-MCP proxy target | | `http://palo-mcp:8788` | Docker network only | MCP service behind the TLS proxy | +| `http://palo-guide-mcp:8789` | Docker network only | Read-only PALO Guide MCP service behind the TLS proxy | | `https://governance.paloframework.org/gateway` | Internet, authenticated | n8n/Dify adapter base URL | | `https://governance.paloframework.org/mcp` | Internet, authenticated | Streamable HTTP MCP endpoint | +| `https://governance.paloframework.org/mcp-guide` | Internet, separately authenticated | Three read-only PALO Guide tools after this release is deployed | `8181` is therefore not the public endpoint. It remains private even when the complete stack runs online on the VPS. @@ -50,6 +54,7 @@ Both variants provide: - PALO Gateway and MCP containers built from this repository; - HTTPS termination and redirect through existing nginx/Certbot or Caddy 2.11.4; - separate Docker secret files for Gateway, MCP and HMAC material; +- a separate Guide MCP secret and allowlist containing only the three read-only guide tools; - persistent PALO data and Caddy certificate volumes; - non-root PALO containers, read-only filesystems, dropped capabilities and health checks; - an explicit MCP host allowlist; @@ -96,6 +101,17 @@ sh setup-secrets.sh The generated `.env` and `secrets/` contents are ignored by Git. Back them up through a protected secret-management process; never upload or commit them. +When upgrading an existing deployment that already has the original three secret files, create only the new Guide MCP token before starting the updated Compose project: + +```bash +umask 077 +test ! -e secrets/guide-mcp-token +openssl rand -hex 32 > secrets/guide-mcp-token +chmod 600 secrets/guide-mcp-token +``` + +Do not rerun `setup-secrets.sh` over an existing deployment because it deliberately refuses to overwrite any current secret. + ## Firewall Preserve SSH access before enabling a firewall. A typical UFW policy is: @@ -110,7 +126,7 @@ sudo ufw allow 443/udp sudo ufw enable ``` -Do not open 8181, 8787, 8788, 18877 or 18878 publicly. The Hostinger Compose variant publishes 18877 and 18878 only on the VPS loopback interface; the clean-VPS variant keeps its administration binding on loopback as documented in its Compose file. +Do not open 8181, 8787, 8788, 8789, 18877, 18878 or 18879 publicly. The Hostinger Compose variant publishes 18877, 18878 and 18879 only on the VPS loopback interface; the clean-VPS variant keeps its administration binding on loopback as documented in its Compose file. ## Start the online stack @@ -158,6 +174,8 @@ Expected public endpoints: ```text https://governance.paloframework.org/mcp-health https://governance.paloframework.org/mcp +https://governance.paloframework.org/mcp-guide-health +https://governance.paloframework.org/mcp-guide https://governance.paloframework.org/gateway/v1/registry https://governance.paloframework.org/gateway/v1/actions/verify ``` @@ -182,8 +200,9 @@ sh smoke-online.sh This checks: -- the public MCP health endpoint over HTTPS; -- rejection of an anonymous MCP request; +- the operational and Guide MCP health endpoints over HTTPS; +- rejection of anonymous operational and Guide MCP requests; +- authenticated Guide MCP initialization; - authenticated access to the public Gateway registry. Inspect service-local health when troubleshooting: @@ -217,11 +236,22 @@ Authorization: Bearer Expose only the PALO-governed tools to an agent. Do not make equivalent privileged target tools available through a parallel ungoverned MCP server. +For products that only need PALO explanation, deterministic route inference and integration planning, use the separate guide-only endpoint and `secrets/guide-mcp-token`: + +```text +Endpoint: https://governance.paloframework.org/mcp-guide +Authorization: Bearer +Tools: palo_explain_framework, palo_infer_governance_route, palo_plan_product_integration +``` + +Issue a distinct secret per deployment boundary when moving beyond the single-tenant developer preview. Never place this token in public browser JavaScript. + ## Public-route boundary The public reverse proxy currently exposes: - MCP `/mcp` and its health endpoint; the configured remote tool allowlist remains decision/status oriented and excludes administrative and execution tools; +- Guide MCP `/mcp-guide` and its health endpoint, authenticated with a separate secret and limited to three read-only guide tools; - Gateway health and authenticated registry read; - authenticated Action Claim verification and full-cycle governed execution; - authenticated execution detail, outcome read and explicit re-verification addressed by execution ID; diff --git a/dist/examples/agentic-interface/mcp-server-spec.json b/dist/examples/agentic-interface/mcp-server-spec.json index e751307..57ec693 100644 --- a/dist/examples/agentic-interface/mcp-server-spec.json +++ b/dist/examples/agentic-interface/mcp-server-spec.json @@ -19,9 +19,16 @@ "PALO_DATA_DIR": "Private runtime directory containing palo-agentic.sqlite.", "PALO_HMAC_KEYS_JSON": "Protected keyId-to-secret map; each secret must contain at least 32 bytes.", "PALO_MCP_HTTP_TOKEN": "Bearer token of at least 24 bytes for Streamable HTTP.", - "PALO_GATEWAY_TOKEN": "Bearer token of at least 24 bytes for the connector REST gateway." + "PALO_GATEWAY_TOKEN": "Bearer token of at least 24 bytes for the connector REST gateway.", + "PALO_MCP_EXPOSED_TOOLS": "Optional comma-separated least-privilege allowlist for stdio and Streamable HTTP. For guidance-only integrations expose only palo_explain_framework, palo_infer_governance_route and palo_plan_product_integration." }, + "prompts": [ + { "name": "palo_guide_agent", "contract": "source-grounded host-agent behavior with explicit inference and authority boundaries" } + ], "tools": [ + { "name": "palo_explain_framework", "contract": "read-only explanation over released semantic records and evidence/authority classes" }, + { "name": "palo_infer_governance_route", "contract": "deterministic signal-to-phase starting hypothesis with reasons, artifacts and open questions" }, + { "name": "palo_plan_product_integration", "contract": "least-privilege MCP transport and integration-class plan that separates guidance from protected execution" }, { "name": "palo_register_agent", "contract": "locally registered versioned agent and authority profile; publisher identity is not authenticated" }, { "name": "palo_register_policy", "contract": "locally registered versioned OPA policy manifest; bundle attestation is not provided" }, { "name": "palo_register_executor", "contract": "versioned executor manifest; executable handler is operator-provisioned" }, diff --git a/dist/index.html b/dist/index.html index 0ee8d25..f001453 100644 --- a/dist/index.html +++ b/dist/index.html @@ -179,11 +179,9 @@

    @@ -197,6 +195,7 @@

    Allowed is not verified.

    Give PALO one AI use case. Leave with a traceable, reviewable evidence dossier in less than ten minutes.

    No account. No mandatory telemetry. Voluntary export only.

    @@ -236,7 +235,7 @@

    Choose the governance problem, not the pro
    01 / PALO Framework

    Govern the AI lifecycle

    Executive, Governance, Risk, Product owner, Auditor

    Frame the use case, classify risk, assess impacts, select controls, define measurements and connect evidence to review.

    OutcomeProportionate route, Case File or evidence bundle, reviewable decision trail

    - +
    02 / PALO-AM

    Govern agentic systems

    Governance, Product, Risk, Assurance, Engineering

    @@ -279,7 +278,7 @@

    PALO-AI: from authorized action to verified outco

    Start from an outcome. Leave with an artifact.

    These are working guided flows, not a flat catalogue. The cognitive start recommends which one matters now.

    -
    Orient

    Stakeholder Onboarding

    Find the proportional route for your role and objective.

    Artifact: Personal route and local Case File handoffStart the route
    +
    Orient

    PALO Guide

    Find a transparent route for your role, objective, system and impact.

    Artifact: Accountable steps and integration classAsk PALO
    Govern agent actions

    Governance Hub builder

    Bind purpose, identity, authority, oversight and verified effects in eight steps.

    Artifact: Governance profile and enforcement summaryOpen the builder
    Connect evidence

    Assessment Path

    Route classification, impact, controls and evidence.

    Artifact: Versioned evidence bundleOpen Assessment Path
    Bound delegation

    PALO-AM Simulator

    Test action space, autonomy and reversibility.

    Artifact: Agentic authority tierOpen PALO-AM
    @@ -292,6 +291,12 @@

    Start from an outcome. Leave with an artifact. +
    + + Explore framework background and specialist modules + History, principles, complementary lifecycle context and the full module catalogue + +
    @@ -508,10 +513,10 @@

    Evaluation

    Ethical, technical, business, and legal.

    - + 5 - Phases -

    From ideation to decommissioning.

    + System activities +

    Ideation through responsible retirement.

    @@ -643,18 +648,18 @@

    Societal & Environmental Well- - +
    -

    Five accountable decisions

    -

    The PALO Lifecycle

    +

    Complementary system-lifecycle view

    +

    Five system lifecycle activities

    -

    A structured roadmap from ideation to responsible retirement. Each phase produces the context and evidence needed by the next.

    +

    This implementation roadmap from ideation to retirement complements, and does not replace, the canonical six-phase PALO governance loop: Frame, Classify, Assess, Control, Measure, Prove & Review.

    -
      +
      1. @@ -698,8 +703,8 @@

        Decommissioning

      -

      Not sure where your work should enter the lifecycle?

      - Find your PALO path +

      Not sure where governance should enter this system lifecycle?

      + Find your PALO route
    @@ -939,7 +944,7 @@

    The Poisoning Boomerang

  • 6 poisoning toolsCompare tarpits, perturbations, and labyrinths.
  • 5 detection strategiesMove from policy analysis to spectral checks.
  • Regulatory analysisUnderstand data integrity and resilience tensions.
  • -
  • Lifecycle controlsMap poisoning risks across all five PALO phases.
  • +
  • Lifecycle controlsMap poisoning risks across the five system lifecycle activities.
  • @@ -1050,7 +1055,7 @@

  • - v2.0.0 - PALO-AM Agentic Governance Modality: New PALO extension for governing AI agents and agentic systems. Features five operational object cards (Identity, Authority, Risk Matrix, Control Layer, Evidence Layer), the Action-Space vs Autonomy Matrix with four tiers, PALO five-phase lifecycle overlay for agentic systems, 11 KPI/KRI indicators and worked enterprise scenarios. Aligned with IMDA MGF v1.5, EU AI Act, ISO/IEC 42001/42005 and NIST AI RMF. + v2.0.0 - PALO-AM Agentic Governance Modality: New PALO extension for governing AI agents and agentic systems. Features five operational object cards (Identity, Authority, Risk Matrix, Control Layer, Evidence Layer), the Action-Space vs Autonomy Matrix with four tiers, a complementary five-activity system lifecycle overlay for agentic systems, 11 KPI/KRI indicators and worked enterprise scenarios. Aligned with IMDA MGF v1.5, EU AI Act, ISO/IEC 42001/42005 and NIST AI RMF.
  • @@ -1118,7 +1123,7 @@

    PALO Governance Notes: Data poisoning recognized as a - cross-cutting risk across all 5 PALO lifecycle phases - new compliance + cross-cutting risk across all five system lifecycle activities - new compliance advisories for Article 10 & 15 obligations, FRIA integration guidance, and data integrity KPI recommendations

  • @@ -1249,6 +1254,8 @@

    + +

    diff --git a/dist/packages/palo-mcp-server/README.html b/dist/packages/palo-mcp-server/README.html index 6008dc1..5f5594c 100644 --- a/dist/packages/palo-mcp-server/README.html +++ b/dist/packages/palo-mcp-server/README.html @@ -27,6 +27,8 @@

    Start and adoption | Public documentation

    PALO MCP reference server - Developer Preview

    LevelreferenceAudiencetechnical | builderProductPALO CoreStatusCurrent GuidanceRead3 min

    Published HTML view | Source: packages/palo-mcp-server/README.md

    On this page
    1. Safety notice
    2. Full-cycle reference demo
    3. Vendor-neutral enforcement providers
    4. Local validation

    PALO MCP reference server - Developer Preview#

    This package is the non-production reference implementation shipped with PALO-AI v2.5. It demonstrates the official MCP SDK over stdio and experimental bearer-authenticated Streamable HTTP, Action Claim 1.2, Effect Contracts, one-time capabilities, trusted in-process executors, authoritative verifiers, signed receipts, outcome attestations, assurance incidents and a hash-chained SQLite ledger.

    +

    PALO platform v3.0.1 also adds three read-only guide tools and the palo_guide_agent prompt. They explain the released PALO semantic model, infer a transparent starting route and plan a least-privilege product integration without mutating case state. See the PALO Guide Agent and MCP Integration guide. Keep these orientation tools separate from protected-action authorization and execution.

    +

    The VPS reference deployment defines a separately authenticated guide-only route at https://governance.paloframework.org/mcp-guide. It uses its own secret and sets PALO_MCP_EXPOSED_TOOLS to the three read-only guide tools, keeping framework orientation separate from the operational /mcp surface.

    Safety notice#

    Do not use this package to authorize or execute production tools, access sensitive data, or support consequential decisions. It is not an audited security boundary, universal exactly-once executor, production identity service, trusted approval service, compliance certification, or production evidence platform.

    The following controls are not provided in v2.5:

      diff --git a/dist/packages/palo-mcp-server/README.md b/dist/packages/palo-mcp-server/README.md index 84f1dc6..bd2df59 100644 --- a/dist/packages/palo-mcp-server/README.md +++ b/dist/packages/palo-mcp-server/README.md @@ -2,6 +2,10 @@ This package is the non-production reference implementation shipped with PALO-AI v2.5. It demonstrates the official MCP SDK over stdio and experimental bearer-authenticated Streamable HTTP, Action Claim 1.2, Effect Contracts, one-time capabilities, trusted in-process executors, authoritative verifiers, signed receipts, outcome attestations, assurance incidents and a hash-chained SQLite ledger. +PALO platform v3.0.1 also adds three read-only guide tools and the `palo_guide_agent` prompt. They explain the released PALO semantic model, infer a transparent starting route and plan a least-privilege product integration without mutating case state. See the [PALO Guide Agent and MCP Integration](../../docs/palo-guide-agent-and-mcp.md) guide. Keep these orientation tools separate from protected-action authorization and execution. + +The VPS reference deployment defines a separately authenticated guide-only route at `https://governance.paloframework.org/mcp-guide`. It uses its own secret and sets `PALO_MCP_EXPOSED_TOOLS` to the three read-only guide tools, keeping framework orientation separate from the operational `/mcp` surface. + ## Safety notice Do not use this package to authorize or execute production tools, access sensitive data, or support consequential decisions. It is not an audited security boundary, universal exactly-once executor, production identity service, trusted approval service, compliance certification, or production evidence platform. diff --git a/dist/release-manifest.json b/dist/release-manifest.json index 0a028b3..dd96607 100644 --- a/dist/release-manifest.json +++ b/dist/release-manifest.json @@ -112,6 +112,26 @@ "telemetryRequired": false, "accountRequired": false }, + "paloGuideAgent": { + "version": "1.0.0", + "date": "2026-08-13", + "status": "implemented-read-only-inference", + "webEntry": "PALO_Guide.html", + "mcpPrompt": "palo_guide_agent", + "mcpTools": [ + "palo_explain_framework", + "palo_infer_governance_route", + "palo_plan_product_integration" + ], + "inferenceSources": [ + "data/semantic-spine.json", + "data/decision-gates.json", + "data/control-library.json", + "data/kpi-kri-registry.json", + "data/source-registry.json" + ], + "authorityBoundary": "Read-only route orientation; no legal conclusion, certification, case approval, deployment authorization or target-system authority." + }, "operationalEvidenceCore": { "version": "1.0.0", "date": "2026-07-12" @@ -154,6 +174,13 @@ "ontology": "formal/palo-ontology-v3.ttl", "shapes": "formal/palo-ontology-v3.shacl.ttl" }, + "guideAgent": { + "webEntry": "PALO_Guide.html", + "documentation": "docs/palo-guide-agent-and-mcp.html", + "server": "packages/palo-mcp-server/index.js", + "transport": ["stdio", "authenticated-streamable-http"], + "productionUse": false + }, "architecturePreview": { "status": "source-ready", "webEntry": "PALO_AIGovernance.html", diff --git a/dist/sitemap.xml b/dist/sitemap.xml index f09e49d..0fccaa1 100644 --- a/dist/sitemap.xml +++ b/dist/sitemap.xml @@ -62,6 +62,13 @@ 0.9 + + https://paloframework.org/PALO_Guide.html + 2026-08-13 + weekly + 0.9 + + https://paloframework.org/PALO_RegulatoryWatch.html 2026-07-11 diff --git a/docs/palo-ai-vps-deployment.md b/docs/palo-ai-vps-deployment.md index e8e0f87..338b8e2 100644 --- a/docs/palo-ai-vps-deployment.md +++ b/docs/palo-ai-vps-deployment.md @@ -10,6 +10,7 @@ The reference developer-preview endpoint was deployed on 17 July 2026: |---|---| | Public hostname | `https://governance.paloframework.org` | | MCP transport | Streamable HTTP at `/mcp`, bearer-authenticated | +| Guide MCP transport | Prepared Streamable HTTP route at `/mcp-guide`, separately bearer-authenticated; deploy this release before treating it as live | | Gateway | HTTPS under `/gateway`, bearer-authenticated and route-limited | | Policy engine | OPA 1.17.0, Docker-internal only | | TLS | Let's Encrypt ECDSA certificate with automatic renewal | @@ -28,9 +29,12 @@ The deployment deliberately uses both private and public addresses: | `http://palo-gateway:8787` | Docker network only | Gateway behind the TLS proxy | | `http://127.0.0.1:18877` | Current VPS host only | Administrative profile registration over SSH | | `http://127.0.0.1:18878` | Current VPS host only | nginx-to-MCP proxy target | +| `http://127.0.0.1:18879` | Current VPS host only | nginx-to-guide-MCP proxy target | | `http://palo-mcp:8788` | Docker network only | MCP service behind the TLS proxy | +| `http://palo-guide-mcp:8789` | Docker network only | Read-only PALO Guide MCP service behind the TLS proxy | | `https://governance.paloframework.org/gateway` | Internet, authenticated | n8n/Dify adapter base URL | | `https://governance.paloframework.org/mcp` | Internet, authenticated | Streamable HTTP MCP endpoint | +| `https://governance.paloframework.org/mcp-guide` | Internet, separately authenticated | Three read-only PALO Guide tools after this release is deployed | `8181` is therefore not the public endpoint. It remains private even when the complete stack runs online on the VPS. @@ -50,6 +54,7 @@ Both variants provide: - PALO Gateway and MCP containers built from this repository; - HTTPS termination and redirect through existing nginx/Certbot or Caddy 2.11.4; - separate Docker secret files for Gateway, MCP and HMAC material; +- a separate Guide MCP secret and allowlist containing only the three read-only guide tools; - persistent PALO data and Caddy certificate volumes; - non-root PALO containers, read-only filesystems, dropped capabilities and health checks; - an explicit MCP host allowlist; @@ -96,6 +101,17 @@ sh setup-secrets.sh The generated `.env` and `secrets/` contents are ignored by Git. Back them up through a protected secret-management process; never upload or commit them. +When upgrading an existing deployment that already has the original three secret files, create only the new Guide MCP token before starting the updated Compose project: + +```bash +umask 077 +test ! -e secrets/guide-mcp-token +openssl rand -hex 32 > secrets/guide-mcp-token +chmod 600 secrets/guide-mcp-token +``` + +Do not rerun `setup-secrets.sh` over an existing deployment because it deliberately refuses to overwrite any current secret. + ## Firewall Preserve SSH access before enabling a firewall. A typical UFW policy is: @@ -110,7 +126,7 @@ sudo ufw allow 443/udp sudo ufw enable ``` -Do not open 8181, 8787, 8788, 18877 or 18878 publicly. The Hostinger Compose variant publishes 18877 and 18878 only on the VPS loopback interface; the clean-VPS variant keeps its administration binding on loopback as documented in its Compose file. +Do not open 8181, 8787, 8788, 8789, 18877, 18878 or 18879 publicly. The Hostinger Compose variant publishes 18877, 18878 and 18879 only on the VPS loopback interface; the clean-VPS variant keeps its administration binding on loopback as documented in its Compose file. ## Start the online stack @@ -158,6 +174,8 @@ Expected public endpoints: ```text https://governance.paloframework.org/mcp-health https://governance.paloframework.org/mcp +https://governance.paloframework.org/mcp-guide-health +https://governance.paloframework.org/mcp-guide https://governance.paloframework.org/gateway/v1/registry https://governance.paloframework.org/gateway/v1/actions/verify ``` @@ -182,8 +200,9 @@ sh smoke-online.sh This checks: -- the public MCP health endpoint over HTTPS; -- rejection of an anonymous MCP request; +- the operational and Guide MCP health endpoints over HTTPS; +- rejection of anonymous operational and Guide MCP requests; +- authenticated Guide MCP initialization; - authenticated access to the public Gateway registry. Inspect service-local health when troubleshooting: @@ -217,11 +236,22 @@ Authorization: Bearer Expose only the PALO-governed tools to an agent. Do not make equivalent privileged target tools available through a parallel ungoverned MCP server. +For products that only need PALO explanation, deterministic route inference and integration planning, use the separate guide-only endpoint and `secrets/guide-mcp-token`: + +```text +Endpoint: https://governance.paloframework.org/mcp-guide +Authorization: Bearer +Tools: palo_explain_framework, palo_infer_governance_route, palo_plan_product_integration +``` + +Issue a distinct secret per deployment boundary when moving beyond the single-tenant developer preview. Never place this token in public browser JavaScript. + ## Public-route boundary The public reverse proxy currently exposes: - MCP `/mcp` and its health endpoint; the configured remote tool allowlist remains decision/status oriented and excludes administrative and execution tools; +- Guide MCP `/mcp-guide` and its health endpoint, authenticated with a separate secret and limited to three read-only guide tools; - Gateway health and authenticated registry read; - authenticated Action Claim verification and full-cycle governed execution; - authenticated execution detail, outcome read and explicit re-verification addressed by execution ID; diff --git a/docs/palo-guide-agent-and-mcp.md b/docs/palo-guide-agent-and-mcp.md new file mode 100644 index 0000000..6440859 --- /dev/null +++ b/docs/palo-guide-agent-and-mcp.md @@ -0,0 +1,212 @@ +# PALO Guide Agent and MCP Integration + +Status: PALO platform v3.0.1 guide-agent contract. The guide tools are implemented as deterministic, read-only inference over released PALO registries. The protected-action runtime remains a separate PALO-AI v2.5 developer preview. + +## Purpose + +The PALO Guide Agent lets a person or product ask three practical questions without first knowing PALO module names: + +1. How does PALO address this governance question? +2. Which PALO phases, controls and artifacts should this case start with? +3. How should another product consume this guidance through MCP, and when must guidance be separated from protected-action enforcement? + +The agent is deliberately split into two layers: + +```text +host assistant or product UI + -> PALO guide prompt + -> read-only guide tools + -> released semantic spine, gates, controls, indicators and sources + +protected action, only when needed + -> Action Claim + -> policy decision / approval + -> one-time capability + -> PALO-owned executor + -> receipt and outcome verification +``` + +The first layer explains and recommends. It cannot approve a case, determine legal applicability, certify compliance or authorize deployment. The second layer demonstrates a protected-action lifecycle, but remains non-production in the current release. + +## What is implemented + +The reference MCP server exposes one prompt and three guide tools: + +| MCP capability | Purpose | State change | +| --- | --- | --- | +| `palo_guide_agent` prompt | Grounds a host assistant in PALO terminology, sources and authority boundaries | None | +| `palo_explain_framework` | Searches released semantic records and explains relevant phases, modules and artifacts | None | +| `palo_infer_governance_route` | Maps explicit use-case signals to an explainable 2-4 step starting route | None | +| `palo_plan_product_integration` | Selects a transport and integration class, with trust boundaries and a least-privilege tool set | None | + +The inference code is in `packages/palo-mcp-server/guide-agent.js`. It reads: + +- `data/semantic-spine.json`; +- `data/decision-gates.json`; +- `data/control-library.json`; +- `data/kpi-kri-registry.json`; +- `data/source-registry.json`. + +It does not call a model, send telemetry, fetch external content or mutate a Case File. A host assistant can reason over the structured result, but must preserve its sources, input signals, "because" statements, open questions and authority boundary. + +## Inference contract + +### Explain PALO + +Call `palo_explain_framework` with a plain-language question: + +```json +{ + "query": "How should I govern an agent that can update supplier records?", + "audience": "procurement product owner", + "limit": 6 +} +``` + +The result includes the canonical six-phase loop, relevant semantic records, evidence class, expected artifacts and the authority boundary of each record. + +### Infer a starting route + +Call `palo_infer_governance_route` with the use case and only the signals that are known: + +```json +{ + "useCase": "An agent reads invoice evidence and can submit an exception resolution.", + "role": "finance product owner", + "objectives": ["bound delegated action", "prepare review evidence"], + "systemType": "agentic workflow", + "currentState": "pilot", + "signals": { + "systemCanAct": true, + "highImpact": true, + "needsEvidence": true, + "humanReviewDefined": false, + "actionImpact": "reversible-write" + } +} +``` + +The result contains an ordered route, the rules that selected each step, linked modules, expected artifacts, starter controls, indicators and unanswered governance questions. It is a starting hypothesis. The host must let an accountable person confirm or correct it before treating the route as case state. + +### Plan a product integration + +Call `palo_plan_product_integration` before configuring a product: + +```json +{ + "product": "Procurement workflow", + "productCategory": "workflow", + "deployment": "remote", + "transport": "auto", + "systemCanAct": true, + "actionImpact": "consequential-write" +} +``` + +The result chooses one of four explicit integration classes: + +| Class | Use | Important limit | +| --- | --- | --- | +| Guidance only | Explain PALO and recommend a route | No target-system authority | +| Advisory gate | Display a pre-action decision | Bypassable if the target tool remains directly available | +| Governed executor | Keep the target credential behind a PALO-owned broker | Current implementation is a developer preview | +| Workflow admission + governed executor | Reject uncovered workflows and broker protected actions | Requires production identity, RBAC, attestation, HA and connector assurance not supplied here | + +## Local MCP stdio + +Install and validate from the repository root: + +```sh +npm ci +npm run validate:agentic +``` + +Use a private runtime directory and expose only the three read-only guide tools when the product needs guidance: + +```json +{ + "mcpServers": { + "palo-guide": { + "command": "node", + "args": ["/absolute/path/to/PALO/packages/palo-mcp-server/index.js"], + "env": { + "PALO_DATA_DIR": "/private/path/palo-guide-runtime", + "PALO_MCP_EXPOSED_TOOLS": "palo_explain_framework,palo_infer_governance_route,palo_plan_product_integration" + } + } + } +} +``` + +Use absolute paths. Do not place target-system credentials, production records or sensitive case data in this configuration or in guide-tool arguments. + +## Authenticated Streamable HTTP + +For a remote MCP client, terminate TLS at a controlled reverse proxy and configure a strong bearer secret through the deployment secret manager: + +```sh +export PALO_MCP_HTTP_HOST='127.0.0.1' +export PALO_MCP_HTTP_PORT='8788' +export PALO_MCP_HTTP_TOKEN='replace-with-at-least-24-random-bytes' +export PALO_MCP_EXPOSED_TOOLS='palo_explain_framework,palo_infer_governance_route,palo_plan_product_integration' +npm run palo:mcp:http +``` + +Client shape: + +```json +{ + "url": "https://governance.example.org/mcp", + "headers": { + "Authorization": "Bearer " + } +} +``` + +The shared preview token authenticates transport access only. It is not a principal identity, role, reviewer signature, case approval or authorization to operate a production system. + +The supplied VPS deployment provides a separately authenticated guide-only route: + +```text +https://governance.paloframework.org/mcp-guide +``` + +It uses `secrets/guide-mcp-token` and exposes only `palo_explain_framework`, `palo_infer_governance_route` and `palo_plan_product_integration`. Deploy the matching repository release before treating the route as live. + +## Host-agent behavior + +MCP clients that support prompts can load `palo_guide_agent`. Otherwise use the same behavior as a host system instruction: + +1. Call `palo_explain_framework` before explaining a PALO concept. +2. Call `palo_infer_governance_route` before recommending a route. +3. Show the signals used, concise reasons, expected artifact and unresolved questions. +4. Let the user correct the context before creating or changing downstream state. +5. Call `palo_plan_product_integration` before proposing a connector or MCP configuration. +6. Keep guide output separate from Action Claims, approval and protected execution. +7. Never describe a developer-preview control as production-ready or a PALO route as legal advice, certification or deployment approval. + +## Web, desktop and mobile product UX + +Use the same reasoning contract on every surface, but adapt the interaction: + +- **Web desktop:** keep inputs and the inferred route visible together; show "because" reasons beside each phase and artifact. +- **Mobile:** ask only the minimum signals in one vertical flow, then move focus to a concise result; keep configuration code behind disclosure controls. +- **Desktop products:** prefer local stdio for read-only guidance when the MCP client and PALO run on the same trusted machine. +- **Cloud products:** use authenticated Streamable HTTP with a narrow tool allowlist and a backend-for-frontend; never put the bearer token in browser code or browser storage. +- **Products that execute actions:** do not let the guide tool call the privileged target. Introduce the protected-action path as a distinct architecture and preserve the user-visible authority boundary. + +## Verification + +Run the guide and MCP contract tests: + +```sh +node --test packages/palo-mcp-server/guide-agent.test.js packages/palo-mcp-server/mcp.test.js +``` + +Run the complete agentic validation before publishing changes: + +```sh +npm run validate:agentic +``` + +Passing tests confirms the documented reference behavior only. It does not establish production readiness, control effectiveness, legal applicability or independent assurance. diff --git a/docs/palo-v3.0.1-ui-ux-three-wave-analysis.md b/docs/palo-v3.0.1-ui-ux-three-wave-analysis.md new file mode 100644 index 0000000..3fbfc13 --- /dev/null +++ b/docs/palo-v3.0.1-ui-ux-three-wave-analysis.md @@ -0,0 +1,153 @@ +# PALO v3.0.1 UI/UX: detailed analysis and three-wave delivery plan + +Date: 13 August 2026 +Scope: public web platform at `paloframework.org`, desktop at 1440x900 and mobile at 390x844, with focused review of the homepage and Evidence Pack route. +Target: clearer orientation, responsive task continuity, WCAG 2.1 AA-oriented implementation, and a source-grounded PALO Guide Agent that products can consume through MCP. + +## Overall verdict + +PALO v3.0.1 has a credible and visually disciplined first screen. The Evidence Pack gives the platform a concrete entry outcome, the privacy boundary is unusually clear, and the generated mobile route is readable. The principal issue is no longer missing capability; it is excess simultaneous explanation. + +The experience currently asks a new visitor to understand the product hierarchy, choose among multiple public tools, reconcile the six-phase canonical governance loop with older five-phase lifecycle content, and scan a very long homepage. On mobile, an optional monitoring import interrupts the core Evidence Pack task before the form. These are information-architecture and task-priority problems, not a need for a visual rebrand. + +## Captured flow + +### Step 1 - Homepage, desktop - generally healthy, overloaded after entry + +Evidence: `audit/ui-ux-3-wave-2026-08-13/current/01-home-desktop.png`. + +The hero has a single strong proposition, a visible primary action, a useful dossier preview and appropriate reassurance. The command bar, however, presents search plus six destinations before the user has selected a governance goal. Below the v3 sections, legacy content remains fully expanded, duplicating product explanations and modules. + +### Step 2 - Homepage, mobile - strong reflow, excessive vertical commitment + +Evidence: `audit/ui-ux-3-wave-2026-08-13/current/02-home-mobile.png`. + +The 390px layout preserves hierarchy, makes the primary action full-width, maintains readable type and reduces navigation to two 44px controls. The dossier preview follows logically. The rest of the page remains exceptionally long, and the older content is not progressively disclosed. + +### Step 3 - Evidence Pack workspace, mobile - task is interrupted + +Evidence: `audit/ui-ux-3-wave-2026-08-13/current/03-assessment-mobile.png`. + +The preloaded case state, local-first explanation and import/resume controls are clear. The optional PolicyWatcher receiver occupies a large block before the core fields. This gives a secondary post-deployment monitoring capability more visual priority than the primary "build the route" task. + +### Step 4 - Generated route, mobile - healthy and actionable + +Evidence: `audit/ui-ux-3-wave-2026-08-13/current/04-assessment-result-mobile.png`. + +The result lands close to the submit action, has a clear title, explains why four modules were selected and exposes follow-on artifacts. The main opportunity is to make the same visible reasoning available before the user reaches the full Evidence Pack, so first-time orientation and product integration do not depend on knowing a module name. + +## Confirmed strengths + +- The primary proposition is outcome-led: one use case becomes a reviewable dossier. +- Privacy and authority boundaries are visible before interaction: no account, no mandatory telemetry, voluntary export, no certification. +- Ink, teal, surface neutrals and restrained gold create a serious product language without imitating a generic compliance dashboard. +- Mobile hero typography, primary target sizing and single-column reflow work well. +- The generated Evidence Pack route uses plain language and connects recommendations to real modules. +- The platform already has a strong machine-readable foundation: semantic identities, six canonical phases, gate definitions, control/indicator registries and evidence classes. + +## Highest-impact UX risks + +### P1 - Top-level choice overload + +Search plus six command-bar routes competes with the Evidence Pack activation goal. "Agentic Governance", "Governance Hub", "Tools" and "Readiness" are meaningful after orientation, but not all need equivalent first-screen weight. + +**Required change:** make a PALO Guide/route finder the secondary top-level path, keep Evidence Pack primary, and move specialist destinations into contextually relevant sections and search. + +### P1 - Canonical model drift + +The homepage first presents the canonical six-phase loop, then later describes "five phases" as "The PALO Lifecycle". Even if one is intended as system activities and the other as governance phases, the interface does not preserve that distinction. + +**Required change:** use Frame, Classify, Assess, Control, Measure and Prove & Review as the only canonical governance loop. Label any older five-activity model as a complementary system-lifecycle view or demote it behind background disclosure. + +### P1 - Optional mobile content interrupts the primary task + +PolicyWatcher is useful after deployment or during Measure/Prove review, but its receiver appears before the core Evidence Pack form and consumes most of a mobile viewport. + +**Required change:** keep it functional but collapsed or repositioned after the route builder, with a plain "Optional monitoring signal" label. + +### P2 - Homepage length and repeated calls to action + +The page repeats framework explanation, lifecycle, module promotion and multiple routes to the same tools. This makes completeness visible but reduces confidence about what to do now. + +**Required change:** preserve background and specialist content behind one accessible disclosure control. Do not delete deep links or module routes. + +### P2 - Orientation logic is present but fragmented + +Stakeholder Onboarding, search, Platform Map and Assessment Path all contain pieces of "where should I start?" logic. The user must discover the correct surface first. + +**Required change:** add one transparent guide workbench that maps explicit signals to phases, reasons, artifacts and a handoff. Reuse the released registries rather than creating another independent taxonomy. + +## Accessibility risks and evidence limits + +- Visible mobile targets appear appropriately sized, but keyboard order, focus restoration and screen-reader announcements require implementation testing; screenshots cannot establish full conformance. +- The new guide must announce result changes through a status/live region and move focus deliberately only after an explicit submit. +- Progressive disclosure must use native `details/summary` or equivalent semantics, preserve deep-link targets and remain operable by keyboard. +- Code/configuration blocks must wrap or scroll inside a named region without causing document-level horizontal overflow at 360px. +- Color must not be the only signal for integration class, warning, selected state or evidence authority. +- The existing YouTube iframe and third-party content were visible but were not tested for complete assistive-technology behavior. +- No claim of full WCAG conformance is made from this audit. Automated checks and manual keyboard/screen-reader testing remain separate acceptance work. + +## Three delivery waves + +### Wave 1 - Find the route + +Goal: reduce time from landing to a confident first action. + +- Add "Ask PALO" / "Find my route" as the secondary hero action. +- Reduce command-bar competition. +- Keep Evidence Pack primary. +- Collapse legacy/background homepage material by default. +- Remove the visible five-versus-six-phase contradiction. + +Acceptance: + +- A new visitor can state the primary action and secondary orientation path without scrolling. +- All existing deep links remain valid. +- Only one canonical six-phase governance loop is presented as PALO's decision model. + +### Wave 2 - Keep the task continuous on every screen + +Goal: make the main task visually dominant from desktop through 360px mobile. + +- Use a two-pane workbench on wide screens and one vertical path on mobile. +- Keep results adjacent to the action that creates them. +- Demote optional monitoring/import features until they are contextually relevant. +- Preserve 44px targets, focus visibility, semantic headings and zero document overflow. + +Acceptance: + +- Desktop and mobile users can complete a route without navigating elsewhere. +- The mobile Evidence Pack reaches core fields before optional PolicyWatcher detail. +- Keyboard and reduced-motion flows remain complete. + +### Wave 3 - Explain, infer and integrate + +Goal: make PALO usable inside another product without turning guidance into hidden authority. + +- Publish a browser-local `PALO_Guide.html` workbench. +- Expose the same source-grounded inference through `palo_explain_framework`, `palo_infer_governance_route` and `palo_plan_product_integration`. +- Publish the `palo_guide_agent` MCP prompt for host assistants. +- Make the integration class explicit: guidance only, advisory gate, governed executor, or workflow admission + governed executor. +- Keep target credentials, protected execution and outcome verification separate from the guide. + +Acceptance: + +- Every recommendation shows input signals, concise reasons, expected artifact, evidence/authority boundary and open questions. +- A guidance-only product can expose only the three read-only tools through `PALO_MCP_EXPOSED_TOOLS`. +- An acting system is never told that an advisory gate is non-bypassable. +- The interface and MCP result use the same six phases and integration vocabulary. + +## Measurement plan + +Measure locally or with explicitly consented, privacy-preserving analytics only: + +- median time from home load to first route result; +- Evidence Pack start and completion rate by viewport class; +- percentage of inferred routes corrected by the user before handoff; +- most common unresolved questions at handoff, without retaining sensitive case text; +- mobile abandonment before the first core field; +- guide-to-Evidence-Pack, guide-to-PALO-AM and guide-to-integration-guide handoff rate; +- MCP schema/input error rate by tool; +- share of product integrations using a three-tool guidance-only allowlist versus the complete developer-preview toolkit. + +These metrics indicate usability and adoption. They do not establish governance quality, control effectiveness, legal compliance or assurance. diff --git a/examples/agentic-interface/mcp-server-spec.json b/examples/agentic-interface/mcp-server-spec.json index e751307..57ec693 100644 --- a/examples/agentic-interface/mcp-server-spec.json +++ b/examples/agentic-interface/mcp-server-spec.json @@ -19,9 +19,16 @@ "PALO_DATA_DIR": "Private runtime directory containing palo-agentic.sqlite.", "PALO_HMAC_KEYS_JSON": "Protected keyId-to-secret map; each secret must contain at least 32 bytes.", "PALO_MCP_HTTP_TOKEN": "Bearer token of at least 24 bytes for Streamable HTTP.", - "PALO_GATEWAY_TOKEN": "Bearer token of at least 24 bytes for the connector REST gateway." + "PALO_GATEWAY_TOKEN": "Bearer token of at least 24 bytes for the connector REST gateway.", + "PALO_MCP_EXPOSED_TOOLS": "Optional comma-separated least-privilege allowlist for stdio and Streamable HTTP. For guidance-only integrations expose only palo_explain_framework, palo_infer_governance_route and palo_plan_product_integration." }, + "prompts": [ + { "name": "palo_guide_agent", "contract": "source-grounded host-agent behavior with explicit inference and authority boundaries" } + ], "tools": [ + { "name": "palo_explain_framework", "contract": "read-only explanation over released semantic records and evidence/authority classes" }, + { "name": "palo_infer_governance_route", "contract": "deterministic signal-to-phase starting hypothesis with reasons, artifacts and open questions" }, + { "name": "palo_plan_product_integration", "contract": "least-privilege MCP transport and integration-class plan that separates guidance from protected execution" }, { "name": "palo_register_agent", "contract": "locally registered versioned agent and authority profile; publisher identity is not authenticated" }, { "name": "palo_register_policy", "contract": "locally registered versioned OPA policy manifest; bundle attestation is not provided" }, { "name": "palo_register_executor", "contract": "versioned executor manifest; executable handler is operator-provisioned" }, diff --git a/index.html b/index.html index 0ee8d25..f001453 100644 --- a/index.html +++ b/index.html @@ -179,11 +179,9 @@
    @@ -197,6 +195,7 @@

    Allowed is not verified.

    Give PALO one AI use case. Leave with a traceable, reviewable evidence dossier in less than ten minutes.

    No account. No mandatory telemetry. Voluntary export only.

    @@ -236,7 +235,7 @@

    Choose the governance problem, not the pro
    01 / PALO Framework

    Govern the AI lifecycle

    Executive, Governance, Risk, Product owner, Auditor

    Frame the use case, classify risk, assess impacts, select controls, define measurements and connect evidence to review.

    OutcomeProportionate route, Case File or evidence bundle, reviewable decision trail

    - +
    02 / PALO-AM

    Govern agentic systems

    Governance, Product, Risk, Assurance, Engineering

    @@ -279,7 +278,7 @@

    PALO-AI: from authorized action to verified outco

    Start from an outcome. Leave with an artifact.

    These are working guided flows, not a flat catalogue. The cognitive start recommends which one matters now.

    -
    Orient

    Stakeholder Onboarding

    Find the proportional route for your role and objective.

    Artifact: Personal route and local Case File handoffStart the route
    +
    Orient

    PALO Guide

    Find a transparent route for your role, objective, system and impact.

    Artifact: Accountable steps and integration classAsk PALO
    Govern agent actions

    Governance Hub builder

    Bind purpose, identity, authority, oversight and verified effects in eight steps.

    Artifact: Governance profile and enforcement summaryOpen the builder
    Connect evidence

    Assessment Path

    Route classification, impact, controls and evidence.

    Artifact: Versioned evidence bundleOpen Assessment Path
    Bound delegation

    PALO-AM Simulator

    Test action space, autonomy and reversibility.

    Artifact: Agentic authority tierOpen PALO-AM
    @@ -292,6 +291,12 @@

    Start from an outcome. Leave with an artifact. +
    + + Explore framework background and specialist modules + History, principles, complementary lifecycle context and the full module catalogue + +
    @@ -508,10 +513,10 @@

    Evaluation

    Ethical, technical, business, and legal.

    - + 5 - Phases -

    From ideation to decommissioning.

    + System activities +

    Ideation through responsible retirement.

    @@ -643,18 +648,18 @@

    Societal & Environmental Well- - +
    -

    Five accountable decisions

    -

    The PALO Lifecycle

    +

    Complementary system-lifecycle view

    +

    Five system lifecycle activities

    -

    A structured roadmap from ideation to responsible retirement. Each phase produces the context and evidence needed by the next.

    +

    This implementation roadmap from ideation to retirement complements, and does not replace, the canonical six-phase PALO governance loop: Frame, Classify, Assess, Control, Measure, Prove & Review.

    -
      +
      1. @@ -698,8 +703,8 @@

        Decommissioning

      -

      Not sure where your work should enter the lifecycle?

      - Find your PALO path +

      Not sure where governance should enter this system lifecycle?

      + Find your PALO route
    @@ -939,7 +944,7 @@

    The Poisoning Boomerang

  • 6 poisoning toolsCompare tarpits, perturbations, and labyrinths.
  • 5 detection strategiesMove from policy analysis to spectral checks.
  • Regulatory analysisUnderstand data integrity and resilience tensions.
  • -
  • Lifecycle controlsMap poisoning risks across all five PALO phases.
  • +
  • Lifecycle controlsMap poisoning risks across the five system lifecycle activities.
  • @@ -1050,7 +1055,7 @@

  • - v2.0.0 - PALO-AM Agentic Governance Modality: New PALO extension for governing AI agents and agentic systems. Features five operational object cards (Identity, Authority, Risk Matrix, Control Layer, Evidence Layer), the Action-Space vs Autonomy Matrix with four tiers, PALO five-phase lifecycle overlay for agentic systems, 11 KPI/KRI indicators and worked enterprise scenarios. Aligned with IMDA MGF v1.5, EU AI Act, ISO/IEC 42001/42005 and NIST AI RMF. + v2.0.0 - PALO-AM Agentic Governance Modality: New PALO extension for governing AI agents and agentic systems. Features five operational object cards (Identity, Authority, Risk Matrix, Control Layer, Evidence Layer), the Action-Space vs Autonomy Matrix with four tiers, a complementary five-activity system lifecycle overlay for agentic systems, 11 KPI/KRI indicators and worked enterprise scenarios. Aligned with IMDA MGF v1.5, EU AI Act, ISO/IEC 42001/42005 and NIST AI RMF.
  • @@ -1118,7 +1123,7 @@

    PALO Governance Notes: Data poisoning recognized as a - cross-cutting risk across all 5 PALO lifecycle phases - new compliance + cross-cutting risk across all five system lifecycle activities - new compliance advisories for Article 10 & 15 obligations, FRIA integration guidance, and data integrity KPI recommendations

  • @@ -1249,6 +1254,8 @@

    + + diff --git a/packages/palo-mcp-server/README.md b/packages/palo-mcp-server/README.md index 84f1dc6..bd2df59 100644 --- a/packages/palo-mcp-server/README.md +++ b/packages/palo-mcp-server/README.md @@ -2,6 +2,10 @@ This package is the non-production reference implementation shipped with PALO-AI v2.5. It demonstrates the official MCP SDK over stdio and experimental bearer-authenticated Streamable HTTP, Action Claim 1.2, Effect Contracts, one-time capabilities, trusted in-process executors, authoritative verifiers, signed receipts, outcome attestations, assurance incidents and a hash-chained SQLite ledger. +PALO platform v3.0.1 also adds three read-only guide tools and the `palo_guide_agent` prompt. They explain the released PALO semantic model, infer a transparent starting route and plan a least-privilege product integration without mutating case state. See the [PALO Guide Agent and MCP Integration](../../docs/palo-guide-agent-and-mcp.md) guide. Keep these orientation tools separate from protected-action authorization and execution. + +The VPS reference deployment defines a separately authenticated guide-only route at `https://governance.paloframework.org/mcp-guide`. It uses its own secret and sets `PALO_MCP_EXPOSED_TOOLS` to the three read-only guide tools, keeping framework orientation separate from the operational `/mcp` surface. + ## Safety notice Do not use this package to authorize or execute production tools, access sensitive data, or support consequential decisions. It is not an audited security boundary, universal exactly-once executor, production identity service, trusted approval service, compliance certification, or production evidence platform. diff --git a/packages/palo-mcp-server/deployment.test.js b/packages/palo-mcp-server/deployment.test.js index 3741c78..2872cdf 100644 --- a/packages/palo-mcp-server/deployment.test.js +++ b/packages/palo-mcp-server/deployment.test.js @@ -37,6 +37,33 @@ test("public Caddy routes do not expose approval enumeration", async () => { assert.ok(blockedPaths.includes("/gateway/v1/incidents/resolve"), "incident mutation is not exposed by the public reverse proxy"); }); +test("guide MCP has a separate authenticated route and least-privilege service", async () => { + const [caddy, compose, hostCompose, nginx, dockerfile, setupSecrets, smoke] = await Promise.all([ + readFile("deploy/vps/palo-ai/Caddyfile", "utf8"), + readFile("deploy/vps/palo-ai/compose.yaml", "utf8"), + readFile("deploy/vps/palo-ai/compose.host-nginx.yaml", "utf8"), + readFile("deploy/vps/palo-ai/nginx-governance.conf", "utf8"), + readFile("deploy/vps/palo-ai/Dockerfile", "utf8"), + readFile("deploy/vps/palo-ai/setup-secrets.sh", "utf8"), + readFile("deploy/vps/palo-ai/smoke-online.sh", "utf8") + ]); + const expectedTools = "palo_explain_framework,palo_infer_governance_route,palo_plan_product_integration"; + for (const source of [compose, hostCompose]) { + const service = composeService(source, "palo-guide-mcp"); + assert.match(service, new RegExp(`PALO_MCP_EXPOSED_TOOLS: ${expectedTools}`)); + assert.match(service, /PALO_MCP_HTTP_TOKEN_FILE: \/run\/secrets\/palo_guide_mcp_token/); + assert.match(service, /cap_drop:\s*\[ALL\]/); + assert.match(service, /no-new-privileges:true/); + assert.doesNotMatch(service, /palo_verify_action_authority|palo_execute_governed_action|palo_request_approval/); + } + assert.match(caddy, /handle \/mcp-guide[\s\S]*?rewrite \* \/mcp[\s\S]*?reverse_proxy palo-guide-mcp:8789/); + assert.match(nginx, /location = \/mcp-guide[\s\S]*?proxy_pass http:\/\/127\.0\.0\.1:18879\/mcp/); + assert.match(dockerfile, /COPY --chown=node:node data \.\/data/); + assert.match(setupSecrets, /secrets\/guide-mcp-token/); + assert.match(smoke, /mcp-guide-health/); + assert.match(smoke, /Authorization: Bearer \$guide_mcp_token/); +}); + test("palo-mcp retains only the capabilities required to drop privileges", async () => { const compose = await readFile("deploy/vps/palo-ai/compose.yaml", "utf8"); const service = composeService(compose, "palo-mcp"); diff --git a/packages/palo-mcp-server/gateway.js b/packages/palo-mcp-server/gateway.js index bf83951..590d53a 100644 --- a/packages/palo-mcp-server/gateway.js +++ b/packages/palo-mcp-server/gateway.js @@ -42,7 +42,7 @@ async function body(request) { const gateway = createServer(async (request, response) => { try { const url = new URL(request.url, `http://${request.headers.host || "localhost"}`); - if (request.method === "GET" && url.pathname === "/health") return send(response, 200, { status: "ok", service: "palo-governance-gateway", version: "2.5.0", frameworkRelease: "3.0.0", releaseStatus: "developer-preview", assuranceCycle: "full-cycle", productionUse: false }); + if (request.method === "GET" && url.pathname === "/health") return send(response, 200, { status: "ok", service: "palo-governance-gateway", version: "2.5.0", frameworkRelease: "3.0.1", releaseStatus: "developer-preview", assuranceCycle: "full-cycle", productionUse: false }); if (!authorized(request)) return send(response, 401, { error: "unauthorized" }); if (request.method === "GET" && url.pathname === "/v1/demo/catalog" && runtime.demoCatalogState) return send(response, 200, { state: runtime.demoCatalogState, synthetic: true }); if (request.method === "POST" && url.pathname === "/v1/demo/catalog/reset" && runtime.demoCatalogState) { diff --git a/packages/palo-mcp-server/guide-agent.js b/packages/palo-mcp-server/guide-agent.js new file mode 100644 index 0000000..3802963 --- /dev/null +++ b/packages/palo-mcp-server/guide-agent.js @@ -0,0 +1,294 @@ +import { readFileSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const readJson = (relativePath) => JSON.parse(readFileSync(path.join(repositoryRoot, relativePath), "utf8")); + +const semanticSpine = readJson("data/semantic-spine.json"); +const decisionGates = readJson("data/decision-gates.json"); +const controlLibrary = readJson("data/control-library.json"); +const indicatorRegistry = readJson("data/kpi-kri-registry.json"); +const sourceRegistry = readJson("data/source-registry.json"); + +const stageOrder = ["frame", "classify", "assess", "control", "measure", "prove"]; +const stopWords = new Set(["a", "an", "and", "are", "as", "at", "be", "by", "for", "from", "how", "i", "in", "is", "it", "of", "on", "or", "the", "to", "we", "what", "with"]); + +function normalize(value) { + return String(value || "").normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, " ").trim(); +} + +function tokens(value) { + return [...new Set(normalize(value).split(/\s+/).filter((token) => token.length > 1 && !stopWords.has(token)))]; +} + +function textOf(value) { + if (value == null) return ""; + if (typeof value === "string") return value; + if (Array.isArray(value)) return value.map(textOf).join(" "); + if (typeof value === "object") return Object.values(value).map(textOf).join(" "); + return String(value); +} + +function publicHref(href) { + if (!href) return null; + if (/^https?:\/\//i.test(href)) return href; + if (href.startsWith("../../")) return href.slice(6); + if (href.startsWith("../")) return href.slice(3); + return href; +} + +function nodeScore(node, queryTokens, audienceTokens) { + const fields = { + label: normalize(node.label), + role: normalize(node.role), + action: normalize(node.action), + intents: normalize(textOf(node.intents)), + outputs: normalize(textOf(node.outputs)), + properties: normalize(textOf(node.properties)), + stakeholders: normalize(textOf(node.stakeholders)), + phase: normalize(node.phaseId), + type: normalize(node.type) + }; + let score = 0; + for (const token of queryTokens) { + if (fields.label === token) score += 48; + else if (fields.label.includes(token)) score += 32; + if (fields.intents.includes(token)) score += 24; + if (fields.action.includes(token)) score += 16; + if (fields.role.includes(token)) score += 14; + if (fields.outputs.includes(token)) score += 12; + if (fields.properties.includes(token)) score += 9; + if (fields.phase.includes(token) || fields.type.includes(token)) score += 7; + } + for (const token of audienceTokens) if (fields.stakeholders.includes(token) || fields.intents.includes(token)) score += 10; + if (queryTokens.length && queryTokens.every((token) => Object.values(fields).some((field) => field.includes(token)))) score += 18; + if (node.type === "stage") score += 3; + return score; +} + +function stageRecord(stageId) { + const node = semanticSpine.nodes.find((item) => item.type === "stage" && item.id === stageId); + const gate = decisionGates.gates.find((item) => item.gateId === stageId); + const controls = controlLibrary.controls.filter((item) => item.lifecycleGates.includes(stageId)); + const indicators = indicatorRegistry.indicators.filter((item) => item.gateIds.includes(stageId)); + const modules = semanticSpine.nodes.filter((item) => item.type === "module" && item.phaseId === stageId); + return { + id: stageId, + label: node.label, + number: node.number, + coreQuestion: node.properties?.["Core question"], + purpose: gate?.purpose || node.role, + action: node.action, + expectedArtifacts: node.outputs || [], + decisionOptions: gate?.decisionOptions || [], + modules: modules.map((item) => ({ id: item.id, label: item.label, href: publicHref(item.href) })), + controls: controls.map((item) => ({ controlId: item.controlId, title: item.title, controlType: item.controlType })), + indicators: indicators.map((item) => ({ indicatorId: item.indicatorId, type: item.type, name: item.name })), + semanticId: node.semanticId, + evidenceClass: node.evidenceClass, + authorityBoundary: node.authorityBoundary + }; +} + +function addStageScore(scores, reasons, stageId, points, reason) { + scores.set(stageId, (scores.get(stageId) || 0) + points); + const list = reasons.get(stageId) || []; + if (reason && !list.includes(reason)) list.push(reason); + reasons.set(stageId, list); +} + +function integrationClass({ systemCanAct, actionImpact, currentState }) { + if (!systemCanAct || actionImpact === "guidance-only") return "guidance-only"; + if (actionImpact === "read-only") return "advisory-gate"; + if (actionImpact === "consequential-write" || currentState === "production") return "workflow-admission-and-governed-executor"; + return "governed-executor"; +} + +function classExplanation(value) { + return { + "guidance-only": "Expose PALO reasoning and released definitions without granting the guide any target-system authority.", + "advisory-gate": "Ask PALO for a visible decision before the product proceeds, but do not present this as a non-bypassable enforcement boundary.", + "governed-executor": "Keep target credentials behind a PALO-owned broker so an allowed claim is consumed before the protected action executes.", + "workflow-admission-and-governed-executor": "Combine instance-level admission with a PALO-owned executor so alternate privileged paths are rejected and the outcome is separately verified." + }[value]; +} + +export class PaloGuideAgent { + explainFramework({ query, audience = "general", limit = 6 } = {}) { + const cleanQuery = String(query || "").trim(); + if (!cleanQuery) throw new Error("A question or topic is required"); + const queryTokens = tokens(cleanQuery); + const audienceTokens = tokens(audience); + const matches = semanticSpine.nodes + .map((node) => ({ node, score: nodeScore(node, queryTokens, audienceTokens) })) + .filter((item) => item.score > 0) + .sort((left, right) => right.score - left.score || stageOrder.indexOf(left.node.phaseId) - stageOrder.indexOf(right.node.phaseId)) + .slice(0, Math.max(1, Math.min(Number(limit) || 6, 12))) + .map(({ node, score }) => ({ + id: node.id, + label: node.label, + type: node.type, + phaseId: node.phaseId, + relevance: score, + explanation: node.role || node.action || node.properties?.["Core question"], + expectedArtifacts: node.outputs || [], + href: publicHref(node.href), + semanticId: node.semanticId, + evidenceClass: node.evidenceClass, + authorityBoundary: node.authorityBoundary + })); + + return { + format: "palo-guide-explanation", + schemaVersion: "1.0.0", + frameworkRelease: "3.0.1", + semanticVersion: semanticSpine.semanticVersion, + query: cleanQuery, + audience, + answerBoundary: "Source-grounded orientation over released PALO definitions. No legal conclusion, certification, case approval or deployment authorization is produced.", + canonicalLoop: stageOrder.map(stageRecord), + matches, + sourceRegistry: { + status: sourceRegistry.status, + updatedAt: sourceRegistry.updatedAt, + reminder: sourceRegistry.disclaimer + } + }; + } + + inferRoute({ useCase, role = "general", objectives = [], systemType = "ai-system", currentState = "idea", signals = {} } = {}) { + const cleanUseCase = String(useCase || "").trim(); + if (cleanUseCase.length < 3) throw new Error("Describe the AI use case in at least 3 characters"); + const scores = new Map(stageOrder.map((stageId) => [stageId, 0])); + const reasons = new Map(stageOrder.map((stageId) => [stageId, []])); + const combined = normalize([cleanUseCase, role, objectives, systemType].join(" ")); + + addStageScore(scores, reasons, "frame", 18, "Every route starts with an explicit purpose, owner, affected people and operating boundary."); + addStageScore(scores, reasons, "classify", 16, "The initial risk and obligation route must be recorded before controls are selected."); + if (/risk|regulat|legal|classif|high impact|public|health|credit|employment|insurance/.test(combined) || signals.regulatedOrPublic || signals.highImpact) { + addStageScore(scores, reasons, "classify", 24, "The context signals material regulatory, public-sector or impact classification questions."); + addStageScore(scores, reasons, "assess", 18, "Potentially affected rights and people need a proportionate impact review."); + } + if (/agent|autonom|tool|workflow|delegat|action/.test(combined) || signals.systemCanAct) { + addStageScore(scores, reasons, "assess", 30, "The system can use tools or take delegated actions, so identity, authority, autonomy and oversight must be bounded."); + addStageScore(scores, reasons, "control", 26, "Delegated action needs owned technical and human controls before execution."); + addStageScore(scores, reasons, "prove", 14, "Authorization and actual outcome evidence must remain separate and reviewable."); + } + if (/code|develop|software|copilot|vibe/.test(combined) || signals.aiAssistedDevelopment) { + addStageScore(scores, reasons, "control", 24, "AI-assisted delivery needs a pre-tool control path and evidence of the development boundary."); + } + if (/metric|kpi|kri|monitor|drift|operate|production/.test(combined) || signals.needsMetrics || ["pilot", "production", "incident", "review"].includes(currentState)) { + addStageScore(scores, reasons, "measure", 26, "The case needs observable indicators, thresholds, ownership and review cadence."); + } + if (/evidence|audit|board|review|dossier|prove/.test(combined) || signals.needsEvidence || ["production", "incident", "review"].includes(currentState)) { + addStageScore(scores, reasons, "prove", 28, "The decision must be reconstructable from versioned evidence, exceptions and source status."); + } + if (currentState === "incident") { + addStageScore(scores, reasons, "control", 20, "An incident requires containment, escalation and compensating-action controls."); + addStageScore(scores, reasons, "measure", 24, "Incident signals and triage timing need to be measured."); + addStageScore(scores, reasons, "prove", 30, "The incident, response and reopening decision require an accountable evidence record."); + } + if (signals.uncertainScope) { + addStageScore(scores, reasons, "frame", 20, "Uncertain scope should be resolved before downstream governance choices are treated as stable."); + addStageScore(scores, reasons, "classify", 12, "Unknown applicability must remain an explicit open review question."); + } + + const selected = stageOrder + .map((stageId) => ({ stageId, score: scores.get(stageId) || 0 })) + .filter((item) => item.score >= 18) + .sort((left, right) => right.score - left.score || stageOrder.indexOf(left.stageId) - stageOrder.indexOf(right.stageId)) + .slice(0, 4) + .sort((left, right) => stageOrder.indexOf(left.stageId) - stageOrder.indexOf(right.stageId)); + if (!selected.some((item) => item.stageId === "prove") && (signals.systemCanAct || signals.needsEvidence || ["production", "incident", "review"].includes(currentState))) { + if (selected.length === 4) selected.pop(); + selected.push({ stageId: "prove", score: scores.get("prove") || 18 }); + selected.sort((left, right) => stageOrder.indexOf(left.stageId) - stageOrder.indexOf(right.stageId)); + } + + const actionImpact = signals.actionImpact || (signals.systemCanAct ? "reversible-write" : "guidance-only"); + const recommendedIntegrationClass = integrationClass({ systemCanAct: Boolean(signals.systemCanAct), actionImpact, currentState }); + return { + format: "palo-governance-route-inference", + schemaVersion: "1.0.0", + frameworkRelease: "3.0.1", + semanticVersion: semanticSpine.semanticVersion, + input: { useCase: cleanUseCase, role, objectives, systemType, currentState, signals: { ...signals, actionImpact } }, + inferenceMethod: "Deterministic signal-to-phase rules over released PALO semantic, gate, control and indicator registries.", + route: selected.map(({ stageId, score }, index) => ({ + position: index + 1, + score, + reasons: reasons.get(stageId), + ...stageRecord(stageId) + })), + integration: { + class: recommendedIntegrationClass, + explanation: classExplanation(recommendedIntegrationClass), + nextTool: "palo_plan_product_integration" + }, + openQuestions: [ + !signals.accountableOwner ? "Who owns the case and can accept, condition, hold, redesign or stop it?" : null, + signals.systemCanAct && !signals.humanReviewDefined ? "Which actions require human review, and can the reviewer actually pause or change the outcome?" : null, + signals.highImpact && !signals.officialSourcesReviewed ? "Which current official sources establish applicability for this context?" : null, + !signals.evidenceLocationDefined ? "Where will versioned evidence, exceptions and review decisions be retained?" : null + ].filter(Boolean), + authorityBoundary: "This route is an explainable starting hypothesis. Accountable people must validate applicability, controls, evidence and the decision to proceed.", + disclaimer: decisionGates.disclaimer + }; + } + + planIntegration({ product, productCategory = "business-app", deployment = "local", transport = "auto", systemCanAct = false, actionImpact = "guidance-only" } = {}) { + const cleanProduct = String(product || "").trim(); + if (!cleanProduct) throw new Error("A product or integration surface is required"); + const selectedClass = integrationClass({ systemCanAct: Boolean(systemCanAct), actionImpact, currentState: deployment === "production" ? "production" : "pilot" }); + const selectedTransport = transport !== "auto" ? transport : deployment === "local" ? "stdio" : "streamable-http"; + const guideTools = ["palo_explain_framework", "palo_infer_governance_route", "palo_plan_product_integration"]; + const protectedActionTools = selectedClass === "guidance-only" ? [] : ["palo_verify_action_authority", ...(selectedClass.includes("governed-executor") ? ["palo_execute_governed_action", "palo_get_execution_status"] : [])]; + const config = selectedTransport === "stdio" + ? { command: "node", args: ["/absolute/path/to/PALO/packages/palo-mcp-server/index.js"], environment: { PALO_DATA_DIR: "/private/path/palo-runtime" } } + : { url: "https://governance.example.org/mcp", headers: { Authorization: "Bearer " } }; + return { + format: "palo-product-integration-plan", + schemaVersion: "1.0.0", + frameworkRelease: "3.0.1", + product: cleanProduct, + productCategory, + deployment, + integrationClass: selectedClass, + integrationClassExplanation: classExplanation(selectedClass), + transport: selectedTransport, + architecture: [ + `${cleanProduct} MCP client`, + "PALO guide tools (read-only inference)", + "Released semantic spine, decision gates, control and indicator registries", + ...(protectedActionTools.length ? ["PALO Action Claim and policy decision", "PALO-owned executor and outcome verifier"] : []), + "Accountable human review and evidence record" + ], + exposedTools: [...guideTools, ...protectedActionTools], + implementationSteps: [ + "Connect the product MCP client using the selected transport and an explicit least-privilege tool allowlist.", + "Call palo_infer_governance_route with the use case and explicit signals; present its reasons and authority boundary to the user.", + "Let the user confirm or correct the inferred route before creating or changing case state.", + ...(selectedClass === "guidance-only" ? [] : ["Map every proposed tool call to a canonical Action Claim and fail closed on missing, malformed, unavailable or denied decisions."]), + ...(selectedClass.includes("governed-executor") ? ["Keep the target credential behind the PALO-owned executor and verify the post-state separately from authorization."] : []), + "Retain version, source status, user corrections, outputs and unresolved questions in the evidence record." + ], + exampleClientConfig: config, + trustBoundaries: [ + "MCP transport authentication is not case approval or reviewer identity.", + "The guide tools provide deterministic orientation and must not receive production secrets or raw sensitive records.", + "The current PALO-AI runtime remains a developer preview and is not an audited production authorization boundary.", + selectedClass === "advisory-gate" ? "An advisory gate remains bypassable if the product can still call the target tool directly." : null, + selectedClass.includes("governed-executor") ? "Target credentials must not be exposed through a parallel ungoverned route." : null + ].filter(Boolean), + references: [ + "docs/palo-guide-agent-and-mcp.md", + "docs/palo-ai-governance-integration-guide.md", + "docs/palo-ai-vps-deployment.md", + "PALO_AIProductionReadiness.html" + ] + }; + } +} + +export const paloGuideAgent = new PaloGuideAgent(); diff --git a/packages/palo-mcp-server/guide-agent.test.js b/packages/palo-mcp-server/guide-agent.test.js new file mode 100644 index 0000000..45c24bb --- /dev/null +++ b/packages/palo-mcp-server/guide-agent.test.js @@ -0,0 +1,53 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { PaloGuideAgent } from "./guide-agent.js"; + +const agent = new PaloGuideAgent(); + +test("PALO guide explanations are grounded in released semantic records", () => { + const result = agent.explainFramework({ query: "How do I govern an agent that uses tools?", audience: "product engineering", limit: 5 }); + assert.equal(result.format, "palo-guide-explanation"); + assert.equal(result.frameworkRelease, "3.0.1"); + assert.deepEqual(result.canonicalLoop.map((stage) => stage.id), ["frame", "classify", "assess", "control", "measure", "prove"]); + assert.ok(result.matches.some((match) => match.id === "palo-am" || match.phaseId === "assess")); + assert.ok(result.matches.every((match) => match.evidenceClass && match.authorityBoundary)); + assert.match(result.answerBoundary, /No legal conclusion/i); +}); + +test("agentic use cases receive an explainable bounded route", () => { + const result = agent.inferRoute({ + useCase: "An invoice agent reads evidence and can draft then submit an exception resolution", + role: "finance product owner", + objectives: ["govern agent autonomy", "prepare evidence"], + currentState: "pilot", + signals: { systemCanAct: true, highImpact: true, needsEvidence: true, actionImpact: "reversible-write" } + }); + assert.equal(result.format, "palo-governance-route-inference"); + assert.ok(result.route.length >= 2 && result.route.length <= 4); + assert.ok(result.route.some((step) => step.id === "assess")); + assert.ok(result.route.some((step) => step.id === "control")); + assert.ok(result.route.some((step) => step.id === "prove")); + assert.equal(result.integration.class, "governed-executor"); + assert.ok(result.route.every((step) => step.reasons.length && step.expectedArtifacts.length && step.authorityBoundary)); + assert.match(result.authorityBoundary, /starting hypothesis/i); +}); + +test("product integration planning separates guidance from protected execution", () => { + const guidance = agent.planIntegration({ product: "Desktop design assistant", productCategory: "developer-tool", deployment: "local" }); + assert.equal(guidance.integrationClass, "guidance-only"); + assert.equal(guidance.transport, "stdio"); + assert.deepEqual(guidance.exposedTools, ["palo_explain_framework", "palo_infer_governance_route", "palo_plan_product_integration"]); + assert.ok(!guidance.exposedTools.includes("palo_execute_governed_action")); + + const protectedPlan = agent.planIntegration({ product: "Procurement workflow", productCategory: "workflow", deployment: "production", systemCanAct: true, actionImpact: "consequential-write" }); + assert.equal(protectedPlan.integrationClass, "workflow-admission-and-governed-executor"); + assert.equal(protectedPlan.transport, "streamable-http"); + assert.ok(protectedPlan.exposedTools.includes("palo_execute_governed_action")); + assert.ok(protectedPlan.trustBoundaries.some((boundary) => /parallel ungoverned route/i.test(boundary))); +}); + +test("guide inputs fail closed when the required context is missing", () => { + assert.throws(() => agent.explainFramework({ query: "" }), /required/i); + assert.throws(() => agent.inferRoute({ useCase: "AI" }), /at least 3/i); + assert.throws(() => agent.planIntegration({ product: "" }), /required/i); +}); diff --git a/packages/palo-mcp-server/http.js b/packages/palo-mcp-server/http.js index 954be68..906d3f5 100644 --- a/packages/palo-mcp-server/http.js +++ b/packages/palo-mcp-server/http.js @@ -4,7 +4,7 @@ import { pathToFileURL } from "node:url"; import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"; import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js"; import { GovernanceRuntime } from "./core.js"; -import { createPaloMcpServer } from "./server.js"; +import { createPaloMcpServer, parseExposedTools } from "./server.js"; import { loadEnforcementProviderFromEnvironment } from "./providers/from-environment.js"; function authorized(header, token) { @@ -22,7 +22,7 @@ export function createAuthenticatedMcpApp({ runtime, token, host = "127.0.0.1", const isLoopback = ["127.0.0.1", "localhost", "::1"].includes(normalizedHost); if (!isLoopback && allowedHosts.length === 0) throw new Error("PALO_MCP_ALLOWED_HOSTS is required when MCP binds to a non-local interface"); const app = createMcpExpressApp({ host, ...(allowedHosts.length ? { allowedHosts } : {}) }); - app.get("/health", (_request, response) => response.json({ status: "ok", service: "palo-mcp-streamable-http", version: "2.5.0", frameworkRelease: "3.0.0", releaseStatus: "developer-preview", assuranceCycle: "full-cycle", productionUse: false })); + app.get("/health", (_request, response) => response.json({ status: "ok", service: "palo-mcp-streamable-http", version: "2.5.0", frameworkRelease: "3.0.1", releaseStatus: "developer-preview", assuranceCycle: "full-cycle", productionUse: false })); app.all("/mcp", async (request, response) => { if (!authorized(request.headers.authorization, token)) return response.status(401).set("WWW-Authenticate", "Bearer").json({ jsonrpc: "2.0", error: { code: -32001, message: "Unauthorized" }, id: null }); if (request.method !== "POST") return response.status(405).json({ jsonrpc: "2.0", error: { code: -32000, message: "Method not allowed" }, id: null }); @@ -45,7 +45,7 @@ if (import.meta.url === pathToFileURL(process.argv[1]).href) { const host = process.env.PALO_MCP_HTTP_HOST || "127.0.0.1"; const port = Number(process.env.PALO_MCP_HTTP_PORT || 8788); const allowedHosts = parseAllowedHosts(process.env.PALO_MCP_ALLOWED_HOSTS); - const exposedTools = parseAllowedHosts(process.env.PALO_MCP_EXPOSED_TOOLS); + const exposedTools = parseExposedTools(process.env.PALO_MCP_EXPOSED_TOOLS); const enforcementProvider = await loadEnforcementProviderFromEnvironment(); const runtime = new GovernanceRuntime({ enforcementProvider }); const app = createAuthenticatedMcpApp({ runtime, token, host, allowedHosts, exposedTools: exposedTools.length ? exposedTools : undefined }); diff --git a/packages/palo-mcp-server/index.js b/packages/palo-mcp-server/index.js index e4634c7..8b4d9c4 100644 --- a/packages/palo-mcp-server/index.js +++ b/packages/palo-mcp-server/index.js @@ -1,12 +1,13 @@ #!/usr/bin/env node import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { GovernanceRuntime } from "./core.js"; -import { createPaloMcpServer } from "./server.js"; +import { createPaloMcpServer, parseExposedTools } from "./server.js"; import { loadEnforcementProviderFromEnvironment } from "./providers/from-environment.js"; const enforcementProvider = await loadEnforcementProviderFromEnvironment(); const runtime = new GovernanceRuntime({ enforcementProvider }); -const server = createPaloMcpServer(runtime); +const exposedTools = parseExposedTools(process.env.PALO_MCP_EXPOSED_TOOLS); +const server = createPaloMcpServer(runtime, { exposedTools: exposedTools.length ? exposedTools : undefined }); process.stderr.write("PALO-AI v2.5 FULL-CYCLE DEVELOPER PREVIEW - isolated testing only; not a production authorization or execution boundary.\n"); await server.connect(new StdioServerTransport()); process.on("exit", () => runtime.close()); diff --git a/packages/palo-mcp-server/mcp.test.js b/packages/palo-mcp-server/mcp.test.js index bd561b8..8c29bbd 100644 --- a/packages/palo-mcp-server/mcp.test.js +++ b/packages/palo-mcp-server/mcp.test.js @@ -10,7 +10,8 @@ import { GovernanceRuntime } from "./core.js"; import { createAuthenticatedMcpApp, parseAllowedHosts } from "./http.js"; const expectedTools = [ - "palo_execute_governed_action", "palo_get_approval_status", "palo_get_execution_status", "palo_get_incident", "palo_get_registry", "palo_list_approvals", "palo_list_incidents", + "palo_execute_governed_action", "palo_explain_framework", "palo_get_approval_status", "palo_get_execution_status", "palo_get_incident", "palo_get_registry", "palo_infer_governance_route", "palo_list_approvals", "palo_list_incidents", + "palo_plan_product_integration", "palo_register_agent", "palo_register_executor", "palo_register_policy", "palo_register_verifier", "palo_request_approval", "palo_resolve_approval", "palo_resolve_incident", "palo_submit_evidence", "palo_verify_action_authority", "palo_verify_evidence", "palo_verify_ledger", "palo_verify_outcome" ]; @@ -34,17 +35,56 @@ test("remote MCP can expose a least-privilege tool subset", async (t) => { const endpoint = new URL(`http://127.0.0.1:${listener.address().port}/mcp`); const transport = new StreamableHTTPClientTransport(endpoint, { requestInit: { headers: { Authorization: `Bearer ${token}` } } }); const client = new Client({ name: "palo-http-subset-test", version: "1.0.0" }); - try { await client.connect(transport); const response = await client.listTools(); assert.deepEqual(response.tools.map((tool) => tool.name).sort(), exposedTools); } + try { + await client.connect(transport); + const response = await client.listTools(); + assert.deepEqual(response.tools.map((tool) => tool.name).sort(), exposedTools); + await assert.rejects(() => client.listPrompts(), /Method not found/); + } finally { await client.close(); } }); test("stdio MCP server advertises the complete governance toolkit", async () => { const transport = new StdioClientTransport({ command: process.execPath, args: ["packages/palo-mcp-server/index.js"], cwd: process.cwd(), stderr: "pipe", env: { ...process.env, PALO_DATA_DIR: path.join(os.tmpdir(), `palo-stdio-${crypto.randomUUID()}`) } }); const client = new Client({ name: "palo-stdio-contract-test", version: "1.0.0" }); - try { await client.connect(transport); const response = await client.listTools(); assert.deepEqual(response.tools.map((tool) => tool.name).sort(), expectedTools); assert.ok(response.tools.every((tool) => tool.inputSchema?.type === "object")); } + try { + await client.connect(transport); + const response = await client.listTools(); + assert.deepEqual(response.tools.map((tool) => tool.name).sort(), expectedTools); + assert.ok(response.tools.every((tool) => tool.inputSchema?.type === "object")); + const prompts = await client.listPrompts(); + assert.ok(prompts.prompts.some((prompt) => prompt.name === "palo_guide_agent")); + const guide = await client.callTool({ name: "palo_infer_governance_route", arguments: { useCase: "An agent can update a product catalog", signals: { systemCanAct: true, actionImpact: "reversible-write" } } }); + assert.equal(guide.structuredContent.integration.class, "governed-executor"); + assert.ok(guide.structuredContent.route.some((step) => step.id === "assess")); + } finally { await client.close(); } }); +test("stdio MCP supports a guidance-only least-privilege allowlist", async () => { + const exposedTools = ["palo_explain_framework", "palo_infer_governance_route", "palo_plan_product_integration"]; + const transport = new StdioClientTransport({ + command: process.execPath, + args: ["packages/palo-mcp-server/index.js"], + cwd: process.cwd(), + stderr: "pipe", + env: { + ...process.env, + PALO_DATA_DIR: path.join(os.tmpdir(), `palo-guide-stdio-${crypto.randomUUID()}`), + PALO_MCP_EXPOSED_TOOLS: exposedTools.join(",") + } + }); + const client = new Client({ name: "palo-guide-stdio-test", version: "1.0.0" }); + try { + await client.connect(transport); + const response = await client.listTools(); + assert.deepEqual(response.tools.map((tool) => tool.name).sort(), exposedTools); + assert.ok(!response.tools.some((tool) => tool.name === "palo_register_agent")); + const prompts = await client.listPrompts(); + assert.ok(prompts.prompts.some((prompt) => prompt.name === "palo_guide_agent")); + } finally { await client.close(); } +}); + test("authenticated Streamable HTTP rejects anonymous clients and exposes the same MCP tools", async (t) => { const dataDir = await mkdtemp(path.join(os.tmpdir(), "palo-http-")); const runtime = new GovernanceRuntime({ dataDir }); const token = "test-streamable-http-token-32-bytes"; const app = createAuthenticatedMcpApp({ runtime, token }); const listener = await new Promise((resolve) => { const server = app.listen(0, "127.0.0.1", () => resolve(server)); }); @@ -52,7 +92,7 @@ test("authenticated Streamable HTTP rejects anonymous clients and exposes the sa const port = listener.address().port; const endpoint = new URL(`http://127.0.0.1:${port}/mcp`); const health = await fetch(`http://127.0.0.1:${port}/health`).then((response) => response.json()); assert.equal(health.version, "2.5.0"); - assert.equal(health.frameworkRelease, "3.0.0"); + assert.equal(health.frameworkRelease, "3.0.1"); assert.equal(health.productionUse, false); const unauthorized = await fetch(endpoint, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "anonymous", version: "1" } } }) }); assert.equal(unauthorized.status, 401); diff --git a/packages/palo-mcp-server/server.js b/packages/palo-mcp-server/server.js index c609117..276513d 100644 --- a/packages/palo-mcp-server/server.js +++ b/packages/palo-mcp-server/server.js @@ -1,16 +1,65 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import * as z from "zod/v4"; import { GovernanceRuntime } from "./core.js"; +import { paloGuideAgent } from "./guide-agent.js"; const jsonObject = z.record(z.string(), z.unknown()); const result = (value) => ({ content: [{ type: "text", text: JSON.stringify(value, null, 2) }], structuredContent: value }); const fail = (error) => ({ isError: true, content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }] }); const guarded = (handler) => async (input) => { try { return result(await handler(input)); } catch (error) { return fail(error); } }; +export function parseExposedTools(value) { + return [...new Set(String(value || "").split(",").map((name) => name.trim()).filter(Boolean))]; +} + export function createPaloMcpServer(runtime = new GovernanceRuntime(), { exposedTools } = {}) { const server = new McpServer({ name: "palo-governance-server", version: "2.5.0", websiteUrl: "https://paloframework.org/PALO_AgenticGovernance.html" }); const allowed = exposedTools ? new Set(exposedTools) : null; + const guideToolNames = ["palo_explain_framework", "palo_infer_governance_route", "palo_plan_product_integration"]; const registerTool = (name, definition, handler) => { if (!allowed || allowed.has(name)) server.registerTool(name, definition, handler); }; + registerTool("palo_explain_framework", { + description: "Explain how PALO works using the released semantic spine, decision gates and authority boundaries. Read-only orientation; no legal conclusion, certification or approval.", + inputSchema: { + query: z.string().min(1).max(4000), + audience: z.string().min(1).max(200).optional(), + limit: z.number().int().min(1).max(12).optional() + } + }, guarded((input) => paloGuideAgent.explainFramework(input))); + registerTool("palo_infer_governance_route", { + description: "Infer an explainable PALO starting route from explicit use-case signals. The result is a deterministic hypothesis that requires accountable human validation.", + inputSchema: { + useCase: z.string().min(3).max(12000), + role: z.string().min(1).max(200).optional(), + objectives: z.array(z.string().min(1).max(300)).max(12).optional(), + systemType: z.string().min(1).max(200).optional(), + currentState: z.enum(["idea", "pilot", "production", "incident", "review"]).optional(), + signals: z.object({ + systemCanAct: z.boolean().optional(), + regulatedOrPublic: z.boolean().optional(), + highImpact: z.boolean().optional(), + aiAssistedDevelopment: z.boolean().optional(), + needsMetrics: z.boolean().optional(), + needsEvidence: z.boolean().optional(), + uncertainScope: z.boolean().optional(), + accountableOwner: z.boolean().optional(), + humanReviewDefined: z.boolean().optional(), + officialSourcesReviewed: z.boolean().optional(), + evidenceLocationDefined: z.boolean().optional(), + actionImpact: z.enum(["guidance-only", "read-only", "reversible-write", "consequential-write"]).optional() + }).optional() + } + }, guarded((input) => paloGuideAgent.inferRoute(input))); + registerTool("palo_plan_product_integration", { + description: "Plan how a product should consume PALO guide tools over MCP and, where relevant, separate guidance from protected-action enforcement.", + inputSchema: { + product: z.string().min(1).max(500), + productCategory: z.enum(["agent", "workflow", "developer-tool", "business-app", "chat-assistant", "other"]).optional(), + deployment: z.enum(["local", "same-network", "remote", "production"]).optional(), + transport: z.enum(["auto", "stdio", "streamable-http"]).optional(), + systemCanAct: z.boolean().optional(), + actionImpact: z.enum(["guidance-only", "read-only", "reversible-write", "consequential-write"]).optional() + } + }, guarded((input) => paloGuideAgent.planIntegration(input))); registerTool("palo_register_agent", { description: "Developer preview: register or version a local PALO agent authority profile; publisher identity is not authenticated.", inputSchema: { caseId: z.string().min(1), profile: jsonObject } }, guarded(({ caseId, profile }) => runtime.registerAgent(caseId, profile))); registerTool("palo_register_policy", { description: "Developer preview: register a local OPA policy manifest; bundle attestation is not provided.", inputSchema: { policy: jsonObject } }, guarded(({ policy }) => runtime.registerPolicy(policy))); registerTool("palo_get_registry", { description: "List locally registered profile and policy versions without secret material.", inputSchema: {} }, guarded(() => runtime.getRegistry())); @@ -30,5 +79,30 @@ export function createPaloMcpServer(runtime = new GovernanceRuntime(), { exposed registerTool("palo_list_incidents", { description: "List assurance incidents opened after mismatched or inconclusive outcomes.", inputSchema: { status: z.enum(["open", "acknowledged", "resolved", "all"]).optional() } }, guarded(({ status }) => runtime.listIncidents(status || "open"))); registerTool("palo_get_incident", { description: "Read one assurance incident.", inputSchema: { incidentId: z.string().min(1) } }, guarded(({ incidentId }) => runtime.getIncident(incidentId))); registerTool("palo_resolve_incident", { description: "Acknowledge or resolve an assurance incident; compensation remains a separately governed Action Claim.", inputSchema: { incidentId: z.string().min(1), status: z.enum(["acknowledged", "resolved"]), resolvedBy: z.string().min(1), resolution: z.string().min(1).max(4000) } }, guarded(({ incidentId, status, resolvedBy, resolution }) => runtime.resolveIncident(incidentId, status, resolvedBy, resolution))); + if (!allowed || guideToolNames.every((name) => allowed.has(name))) server.registerPrompt("palo_guide_agent", { + title: "PALO governance guide agent", + description: "Ground an assistant in PALO v3.0.1 and make route inference, evidence and product-integration boundaries explicit.", + argsSchema: { + audience: z.string().min(1).max(200).optional(), + product: z.string().min(1).max(500).optional() + } + }, ({ audience = "general", product = "the user's product" }) => ({ + description: "PALO source-grounded guide agent instructions", + messages: [{ + role: "user", + content: { + type: "text", + text: [ + "Act as the PALO governance guide for " + audience + ".", + "Use palo_explain_framework before explaining PALO concepts, palo_infer_governance_route before recommending a route, and palo_plan_product_integration before proposing how " + product + " should connect.", + "Treat tool results as released framework orientation, not legal conclusions, certification, case approval or deployment authorization.", + "Show the input signals, concise because-statements, expected artifact, evidence class, authority boundary and unresolved questions.", + "Ask the user to confirm or correct inferred context before any downstream product changes.", + "For systems that can act, keep read-only guidance separate from Action Claims, policy decisions, governed execution and outcome verification.", + "Never imply that an advisory gate is non-bypassable or that the developer-preview PALO-AI runtime is production-ready." + ].join("\n") + } + }] + })); return server; } diff --git a/release-manifest.json b/release-manifest.json index 0a028b3..dd96607 100644 --- a/release-manifest.json +++ b/release-manifest.json @@ -112,6 +112,26 @@ "telemetryRequired": false, "accountRequired": false }, + "paloGuideAgent": { + "version": "1.0.0", + "date": "2026-08-13", + "status": "implemented-read-only-inference", + "webEntry": "PALO_Guide.html", + "mcpPrompt": "palo_guide_agent", + "mcpTools": [ + "palo_explain_framework", + "palo_infer_governance_route", + "palo_plan_product_integration" + ], + "inferenceSources": [ + "data/semantic-spine.json", + "data/decision-gates.json", + "data/control-library.json", + "data/kpi-kri-registry.json", + "data/source-registry.json" + ], + "authorityBoundary": "Read-only route orientation; no legal conclusion, certification, case approval, deployment authorization or target-system authority." + }, "operationalEvidenceCore": { "version": "1.0.0", "date": "2026-07-12" @@ -154,6 +174,13 @@ "ontology": "formal/palo-ontology-v3.ttl", "shapes": "formal/palo-ontology-v3.shacl.ttl" }, + "guideAgent": { + "webEntry": "PALO_Guide.html", + "documentation": "docs/palo-guide-agent-and-mcp.html", + "server": "packages/palo-mcp-server/index.js", + "transport": ["stdio", "authenticated-streamable-http"], + "productionUse": false + }, "architecturePreview": { "status": "source-ready", "webEntry": "PALO_AIGovernance.html", diff --git a/scripts/browser-smoke.mjs b/scripts/browser-smoke.mjs index 3b88b3a..bfff395 100644 --- a/scripts/browser-smoke.mjs +++ b/scripts/browser-smoke.mjs @@ -99,6 +99,43 @@ try { return content; } + const guideNetworkWrites = []; + const trackGuideWrites = (request) => { + if (!["GET", "HEAD", "OPTIONS"].includes(request.method())) guideNetworkWrites.push({ method: request.method(), url: request.url() }); + }; + page.on("request", trackGuideWrites); + await page.goto(`${baseUrl}/PALO_Guide.html`, { waitUntil: "domcontentloaded" }); + await page.evaluate(() => { localStorage.clear(); sessionStorage.clear(); }); + await page.locator("#guide-role").selectOption("engineering"); + await page.locator("#guide-objective").selectOption("integrate-product"); + await page.locator("#guide-system").selectOption("agentic"); + await page.locator("#guide-tools").selectOption("yes"); + await page.locator("#guide-impact").selectOption("high"); + await page.locator("#guide-product").fill("Internal workflow platform"); + await page.locator("#guide-save-local").check(); + await page.locator("#palo-guide-form").evaluate((form) => form.requestSubmit()); + await page.waitForFunction(() => document.documentElement.hasAttribute("data-palo-guide-route")); + await expectAttribute(page.locator("html"), "data-palo-guide-route", "workflow-admission-governed-executor", "PALO Guide agentic integration route"); + if (await page.locator("#palo-guide-route li").count() !== 4) failures.push("PALO Guide: agentic integration route must expose four accountable steps"); + if (!/system can create effects or use tools[\s\S]*declared impact is consequential/i.test(await page.locator("#palo-guide-because").innerText())) failures.push("PALO Guide: visible because statement omits action or impact signals"); + if (!await page.locator('a[href="docs/palo-guide-agent-and-mcp.html"]').first().isVisible()) failures.push("PALO Guide: agent and MCP manual is not visibly linked"); + const storedGuideRoute = await page.evaluate(() => localStorage.getItem(window.__PALO_GUIDE.storageKey)); + if (!storedGuideRoute || !/Internal workflow platform/.test(storedGuideRoute)) failures.push("PALO Guide: explicit device-local save did not retain the declared route"); + await page.locator("#palo-guide-reset").click(); + const clearedGuideRoute = await page.evaluate(() => localStorage.getItem(window.__PALO_GUIDE.storageKey)); + if (clearedGuideRoute !== null) failures.push("PALO Guide: reset did not remove device-local answers"); + page.off("request", trackGuideWrites); + if (guideNetworkWrites.length) failures.push(`PALO Guide: local inference sent a network write (${JSON.stringify(guideNetworkWrites)})`); + + await page.goto(`${baseUrl}/index.html`, { waitUntil: "domcontentloaded" }); + if (await page.locator("details[data-palo-progressive-background]").evaluate((details) => details.open)) failures.push("Homepage: framework background is not collapsed by default"); + await page.evaluate(() => { location.hash = "#lifecycle"; }); + await page.waitForFunction(() => document.querySelector("details[data-palo-progressive-background]")?.open === true); + if (!await page.locator("#lifecycle").isVisible()) failures.push("Homepage: hashchange did not reveal the legacy lifecycle target"); + await page.goto(`${baseUrl}/index.html#principles`, { waitUntil: "domcontentloaded" }); + await page.waitForFunction(() => document.querySelector("details[data-palo-progressive-background]")?.open === true); + if (!await page.locator("#principles").isVisible()) failures.push("Homepage: initial descendant hash did not reveal the background disclosure"); + await page.goto(`${baseUrl}/governance-hub/?role=executive&view=assurance`, { waitUntil: "networkidle" }); await expectAttribute(page.locator("html"), "data-hub-role", "executive", "Governance Hub executive deep link"); await expectAttribute(page.locator("html"), "data-hub-view", "assurance", "Governance Hub assurance deep link"); @@ -163,6 +200,7 @@ try { await page.goto(`${baseUrl}/PALO_AssessmentPath.html`, { waitUntil: "domcontentloaded" }); await page.evaluate(() => { localStorage.clear(); sessionStorage.clear(); }); + if (await page.locator("details.palo-signal-details").evaluate((details) => details.open)) failures.push("Evidence Pack: optional PolicyWatcher receiver is not collapsed by default"); const unknownPreserved = await page.evaluate(() => { const base = window.PALOCaseFile.create({ title: "Unknown-field test", extensions: { vendorExtension: { retained: true } } }); const merged = window.PALOCaseFile.merge(base, { context: { nested: { known: true } }, extraModuleData: { value: 7 } }); @@ -469,7 +507,7 @@ try { for (const viewport of [{ width: 1440, height: 900 }, { width: 1024, height: 768 }, { width: 390, height: 844 }, { width: 360, height: 800 }]) { await page.setViewportSize(viewport); - for (const file of ["index.html", "PALO_AIGovernance.html", "PALO_AIWhy.html", "PALO_AIQuickstarts.html", "PALO_AssessmentPath.html", "PALO_AgenticGovernance.html", "PALO_AgenticCapabilityMatrix.html", "PALO_AIProductionReadiness.html", "PALO_DocumentationLibrary.html", "docs/palo-ai-adoption-paths.html", "PALO_PlatformMap.html", "designs/theory-to-practice-infographic/index.html?mode=navigation"]) { + for (const file of ["index.html", "PALO_Guide.html", "PALO_AIGovernance.html", "PALO_AIWhy.html", "PALO_AIQuickstarts.html", "PALO_AssessmentPath.html", "PALO_AgenticGovernance.html", "PALO_AgenticCapabilityMatrix.html", "PALO_AIProductionReadiness.html", "PALO_DocumentationLibrary.html", "docs/palo-ai-adoption-paths.html", "PALO_PlatformMap.html", "designs/theory-to-practice-infographic/index.html?mode=navigation"]) { await page.goto(`${baseUrl}/${file}`, { waitUntil: "domcontentloaded" }); if (file.includes("mode=navigation")) { const onboardingSeparators = page.locator(".route-ribbon > .route-separator"); @@ -483,6 +521,13 @@ try { })); if (routeMap.entries !== 3 || routeMap.visibleAudiences !== 3 || !routeMap.lineageVisible) failures.push(`Homepage at ${viewport.width}x${viewport.height}: route lineage or audience labels are hidden (${JSON.stringify(routeMap)})`); } + if (file === "PALO_Guide.html" && viewport.width <= 390) { + const undersizedGuideTargets = await page.evaluate(() => { + const selectors = ["#palo-guide-form select", "#palo-guide-form input[type=\"text\"]", "#palo-guide-form button", "#palo-guide-form .palo-guide-save", ".palo-guide-copy", ".palo-guide-handoff-ledger a"]; + return selectors.flatMap((selector) => Array.from(document.querySelectorAll(selector))).filter((node) => node.offsetParent !== null && !node.hidden && node.getBoundingClientRect().height < 43.5).map((node) => `${node.id || node.className || node.tagName}:${node.getBoundingClientRect().height}`); + }); + if (undersizedGuideTargets.length) failures.push(`PALO Guide at ${viewport.width}x${viewport.height}: interactive targets below 44px (${undersizedGuideTargets.join(", ")})`); + } if (file.includes("mode=navigation")) { await page.waitForFunction(() => window.__graphReady === true, null, { timeout: 30_000 }); if (viewport.width <= 390) { diff --git a/scripts/public-files.mjs b/scripts/public-files.mjs index fc24b4b..d024064 100644 --- a/scripts/public-files.mjs +++ b/scripts/public-files.mjs @@ -13,6 +13,7 @@ export const PUBLIC_FILES = [ "PALO_AgenticCapabilityMatrix.html", "PALO_AIProductionReadiness.html", "PALO_AssessmentPath.html", + "PALO_Guide.html", "PALO_AuditBench.html", "PALO_Community.html", "PALO_CompanionApp.html", @@ -47,6 +48,8 @@ export const PUBLIC_FILES = [ "assets/palo-am-nav.js", "assets/palo-assessment-path.js", "assets/palo-case-file.js", + "assets/palo-guide.css", + "assets/palo-guide.js", "assets/palo-platform-map.css", "assets/palo-platform-map.js", "assets/palo-policywatcher-signal.js", @@ -96,6 +99,7 @@ export const PUBLIC_FILES = [ "docs/p1-case-file-and-migration.md", "docs/activation-freeze-2026-08.md", "docs/palo-v3-semantic-foundation.md", + "docs/palo-guide-agent-and-mcp.md", "docs/palo-ai-n8n-alpha-test-report.md", "docs/palo-ai-adoption-paths.md", "docs/palo-ai-cloud-reference-architecture.md", diff --git a/scripts/validate-agentic.mjs b/scripts/validate-agentic.mjs index c1674fb..a632294 100644 --- a/scripts/validate-agentic.mjs +++ b/scripts/validate-agentic.mjs @@ -29,7 +29,7 @@ for (const name of names) { } const expectedTools = [ - "palo_execute_governed_action", "palo_get_approval_status", "palo_get_execution_status", "palo_get_incident", "palo_get_registry", "palo_list_approvals", "palo_list_incidents", + "palo_execute_governed_action", "palo_explain_framework", "palo_get_approval_status", "palo_get_execution_status", "palo_get_incident", "palo_get_registry", "palo_infer_governance_route", "palo_list_approvals", "palo_list_incidents", "palo_plan_product_integration", "palo_register_agent", "palo_register_executor", "palo_register_policy", "palo_register_verifier", "palo_request_approval", "palo_resolve_approval", "palo_resolve_incident", "palo_submit_evidence", "palo_verify_action_authority", "palo_verify_evidence", "palo_verify_ledger", "palo_verify_outcome" ].sort(); diff --git a/scripts/validate.mjs b/scripts/validate.mjs index e79a715..a958720 100644 --- a/scripts/validate.mjs +++ b/scripts/validate.mjs @@ -404,6 +404,30 @@ for (const [file, html] of htmlByFile) { } if (sharedReferenceCount === 0) errors.push("shared assets: no palo-v21.css/js references found"); +const guideHtml = htmlByFile.get("PALO_Guide.html") || ""; +for (const field of ["role", "objective", "systemType", "canAct", "impact", "product"]) { + if (!new RegExp(`name=["']${field}["']`).test(guideHtml)) errors.push(`PALO_Guide.html: deterministic guide input ${field} is missing`); +} +for (const tool of ["palo_explain_framework", "palo_infer_governance_route", "palo_plan_product_integration"]) { + if (!guideHtml.includes(tool)) errors.push(`PALO_Guide.html: MCP guide tool ${tool} is missing`); +} +for (const label of ["Frame", "Classify", "Assess", "Control", "Measure", "Prove & Review"]) { + if (!guideHtml.includes(`${label}`)) errors.push(`PALO_Guide.html: canonical phase ${label} is missing`); +} +if (!/docs\/palo-guide-agent-and-mcp\.html/.test(guideHtml) || !/Browser-local and source-grounded/.test(guideHtml) || !/not a production authorization boundary/i.test(guideHtml)) errors.push("PALO_Guide.html: agent manual, local trust line or production authority boundary is incomplete"); + +const homeOrientationHtml = htmlByFile.get("index.html") || ""; +if (!/data-palo-progressive-background/.test(homeOrientationHtml) || !/Explore framework background and specialist modules/.test(homeOrientationHtml)) errors.push("index.html: legacy background disclosure is missing"); +if (/data-palo-progressive-background[^>]*\sopen(?:\s|=|>)/i.test(homeOrientationHtml)) errors.push("index.html: legacy background disclosure must be collapsed by default"); +if (!/PALO_Guide\.html[^>]*>[\s\S]*?(?:Ask PALO|Find my route)/.test(homeOrientationHtml)) errors.push("index.html: first-class PALO Guide route is missing"); +if (!/Complementary system-lifecycle view[\s\S]*canonical six-phase PALO governance loop/.test(homeOrientationHtml)) errors.push("index.html: five-activity system lifecycle is not explicitly separated from the canonical six-phase loop"); + +const assessmentOrientationHtml = htmlByFile.get("PALO_AssessmentPath.html") || ""; +const assessmentFormIndex = assessmentOrientationHtml.indexOf('id="palo-assessment-form"'); +const assessmentResultsIndex = assessmentOrientationHtml.indexOf('id="assessment-results"'); +const policyWatcherIndex = assessmentOrientationHtml.indexOf('class="palo-signal-details"'); +if (assessmentFormIndex < 0 || assessmentResultsIndex < assessmentFormIndex || policyWatcherIndex < assessmentResultsIndex || !/
    /.test(assessmentOrientationHtml)) errors.push("PALO_AssessmentPath.html: optional PolicyWatcher receiver must follow the form and nearby results in a collapsed disclosure"); + let sitemap = {}; try { sitemap = parseXml("sitemap.xml", await readFile(path.join(validationRoot, "sitemap.xml"), "utf8")); } catch (error) { errors.push(`sitemap.xml: ${error.message}`); } diff --git a/sitemap.xml b/sitemap.xml index f09e49d..0fccaa1 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -62,6 +62,13 @@ 0.9 + + https://paloframework.org/PALO_Guide.html + 2026-08-13 + weekly + 0.9 + + https://paloframework.org/PALO_RegulatoryWatch.html 2026-07-11