mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-19 16:27:37 +00:00
Align AI data handling disclosures
This commit is contained in:
parent
94a5ab1b59
commit
c8d72cf06f
11 changed files with 149 additions and 58 deletions
|
|
@ -95,8 +95,8 @@ The telemetry implementation is in [`internal/telemetry/telemetry.go`](../intern
|
|||
|
||||
Pulse can make outbound connections when you enable specific features:
|
||||
|
||||
- **AI (BYOK)**: when AI features are configured with your own API key, Pulse sends only the context required for your request directly to the provider you chose (OpenAI, Anthropic, etc.). Requests do not transit Pulse infrastructure. See `docs/AI.md`.
|
||||
- **AI (Quickstart)**: when the Pulse-hosted Quickstart provider is selected, your chat request — including messages, system prompt, and tool definitions — is forwarded through `license.pulserelay.pro/v1/quickstart/patrol` to the underlying model provider. This path exists so eligible quickstart users can try AI without their own API key; it means requests transit Pulse infrastructure. To keep prompts off Pulse infrastructure, use a BYOK provider instead.
|
||||
- **AI (BYOK)**: when AI features are configured with your own API key, Pulse sends only the context required for your request directly to the provider you chose (OpenAI, Anthropic, etc.). Requests do not transit Pulse infrastructure. Before non-local model requests leave the instance, governed resource details use the same resource-policy redaction shown in Data Handling: local-only resource details are omitted from detailed prompt sections or replaced with policy-safe summaries, and known restricted resource identifiers are redacted where they appear in provider-bound context. See `docs/AI.md`.
|
||||
- **AI (Quickstart)**: when the Pulse-hosted Quickstart provider is selected, your chat request, including messages, system prompt, and tool definitions, is forwarded through `license.pulserelay.pro/v1/quickstart/patrol` to the underlying model provider. This path exists so eligible quickstart users can try AI without their own API key; it means requests transit Pulse infrastructure. The same resource-policy redaction is applied before the Quickstart request is sent, and the Quickstart proxy requires the runtime to mark the request as using that policy. To keep prompts off Pulse infrastructure entirely, use a BYOK provider instead.
|
||||
- **Relay / Remote Access**: when relay is enabled, Pulse connects to the configured relay endpoint to enable mobile access. See Settings → Remote Access.
|
||||
- **Update checks**: Pulse can check for new releases/updates (for example via GitHub release metadata) depending on your deployment and configuration.
|
||||
|
||||
|
|
|
|||
|
|
@ -3555,6 +3555,102 @@
|
|||
"kind": "file"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "L18",
|
||||
"name": "Policy-aware data governance",
|
||||
"target_score": 6,
|
||||
"current_score": 6,
|
||||
"status": "partial",
|
||||
"completion": {
|
||||
"state": "bounded-residual",
|
||||
"summary": "Policy-aware data governance now has a first-class governed floor: resource sensitivity, handling-boundary, and redaction posture are visible in Data Handling, non-local AI provider requests use the shared resource-policy sanitizer at the final model boundary, hosted quickstart requests carry a resource-policy marker that the proxy enforces, and privacy copy now reflects the runtime behavior. Broader enterprise DLP, provider-retention posture, and non-resource prompt-secret detection remain a named post-RC hardening track.",
|
||||
"tracking": [
|
||||
{
|
||||
"kind": "lane-followup",
|
||||
"id": "policy-aware-data-governance-post-rc-hardening"
|
||||
}
|
||||
]
|
||||
},
|
||||
"blockers": [],
|
||||
"subsystems": [],
|
||||
"evidence": [
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "docs/PRIVACY.md",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "docs/release-control/v6/internal/subsystems/ai-runtime.md",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "docs/release-control/v6/internal/subsystems/security-privacy.md",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "frontend-modern/public/docs/PRIVACY.md",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "frontend-modern/src/components/Settings/AISettingsDialogs.tsx",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "frontend-modern/src/components/Settings/DataHandlingPanel.tsx",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "frontend-modern/src/utils/__tests__/quickstartCopyContract.test.ts",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "internal/ai/modelboundary/resource_policy_sanitizer.go",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "internal/ai/modelboundary/resource_policy_sanitizer_test.go",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "internal/ai/providers/quickstart.go",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "internal/ai/providers/quickstart_test.go",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "internal/unifiedresources/policy_metadata.go",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "internal/unifiedresources/policy_metadata_test.go",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse-pro",
|
||||
"path": "license-server/quickstart_proxy.go",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse-pro",
|
||||
"path": "license-server/quickstart_proxy_test.go",
|
||||
"kind": "file"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"release_gates": [
|
||||
|
|
@ -4250,6 +4346,17 @@
|
|||
"L11"
|
||||
],
|
||||
"subsystem_ids": []
|
||||
},
|
||||
{
|
||||
"id": "policy-aware-data-governance-post-rc-hardening",
|
||||
"summary": "Track broader policy-aware data-governance hardening beyond the current resource-policy floor, including enterprise DLP posture, provider-retention disclosure, non-resource prompt-secret detection, and additional external-model boundary proof where future paid or hosted AI surfaces add new data paths.",
|
||||
"owner": "project-owner",
|
||||
"status": "planned",
|
||||
"recorded_at": "2026-04-25",
|
||||
"lane_ids": [
|
||||
"L18"
|
||||
],
|
||||
"subsystem_ids": []
|
||||
}
|
||||
],
|
||||
"coverage_gaps": [
|
||||
|
|
@ -4311,36 +4418,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "policy-aware-data-governance",
|
||||
"summary": "The current v6 map treats privacy and AI runtime as adjacent concerns, but it does not yet govern sensitivity classification, redaction, local-vs-cloud routing, or AI-safe summary boundaries as a first-class release surface.",
|
||||
"owner": "project-owner",
|
||||
"status": "planned",
|
||||
"recorded_at": "2026-03-17",
|
||||
"lane_ids": [
|
||||
"L6",
|
||||
"L14"
|
||||
],
|
||||
"subsystem_ids": [
|
||||
"ai-runtime",
|
||||
"api-contracts",
|
||||
"security-privacy"
|
||||
],
|
||||
"proposed_resolution": "new-lane",
|
||||
"coverage_impact": 15,
|
||||
"evidence": [
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "docs/release-control/v6/internal/subsystems/security-privacy.md",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"repo": "pulse",
|
||||
"path": "docs/release-control/v6/internal/V6_BRIDGE_RELEASE_FOUNDATION_SPEC.md",
|
||||
"kind": "file"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "resource-change-and-timeline",
|
||||
"summary": "The current v6 lane map proves unified resources and monitoring floors, but the resource-change and cross-resource timeline work is now kept as hidden backend foundation for investigation and AI flows until the surfaced case is proven.",
|
||||
|
|
@ -4516,26 +4593,6 @@
|
|||
"agent-lifecycle"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "policy-aware-data-governance-lane",
|
||||
"name": "Policy-aware data governance",
|
||||
"summary": "Promote sensitivity classification, redaction, local-vs-cloud routing, and AI-safe summary boundaries into a governed product lane rather than leaving them split across privacy and AI runtime residue.",
|
||||
"status": "planned",
|
||||
"recorded_at": "2026-03-17",
|
||||
"target_id": "v6-product-lane-expansion",
|
||||
"current_lane_ids": [
|
||||
"L6",
|
||||
"L14"
|
||||
],
|
||||
"coverage_gap_ids": [
|
||||
"policy-aware-data-governance"
|
||||
],
|
||||
"subsystem_ids": [
|
||||
"ai-runtime",
|
||||
"api-contracts",
|
||||
"security-privacy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "resource-change-intelligence",
|
||||
"name": "Resource change intelligence",
|
||||
|
|
|
|||
|
|
@ -634,6 +634,10 @@ work extends shared components instead of creating new local variants.
|
|||
as Patrol runs or Patrol-only activation support when that is the governed
|
||||
backend truth, and must not drift back to generic hosted-chat or generic
|
||||
AI-credit claims.
|
||||
When a shared settings dialog describes hosted Quickstart transport, it
|
||||
must match the governed privacy boundary: hosted Quickstart routes
|
||||
policy-redacted prompts through Pulse infrastructure, while BYOK providers
|
||||
go direct to the operator's chosen provider.
|
||||
19. Keep sparkline scrubbing source-local and sibling-sync timestamp-based. The chart a user is actively scrubbing in `frontend-modern/src/components/shared/InteractiveSparkline.tsx` and `frontend-modern/src/components/shared/useInteractiveSparklineState.ts` must keep its dashed hover cursor on the real local mouse `x`, while sibling cards may map the shared hover timestamp onto their own timelines. Shared cursor sync must not snap the source chart back onto the nearest sample timestamp, the rendered SVG/canvas hover cursor must bind to the actual numeric cursor coordinate rather than a boolean guard state, the time cursor must span the chart viewport instead of collapsing to the series height, and the hover tooltip must track the pointer instead of anchoring to the chart top edge while following the active theme rather than a hardcoded dark shell.
|
||||
20. Keep shared contextual focus canonical after adoption. Once a summary or table surface enters route-backed contextual focus, future additions must extend `frontend-modern/src/components/shared/contextualFocus.ts` and its guardrail tests rather than forking another helper for workload IDs, resource IDs, or scroll-preserving same-route selection.
|
||||
21. Keep shared infrastructure/resource selectors on the canonical agent-facet
|
||||
|
|
|
|||
|
|
@ -107,6 +107,12 @@ visibility, and privacy controls to operators.
|
|||
7. Keep auth-env ingestion and shared fingerprint-verifier TLS defaults aligned whenever runtime auth loading or pinned-certificate transport behavior changes.
|
||||
8. Keep the Data Handling settings surface neutral and non-commercial: it may show resource policy posture, local-only counts, and redaction coverage, but it must not advertise trials, upgrades, paid plans, or monitoring limits.
|
||||
9. Keep operator-facing Data Handling posture aligned with runtime AI/context enforcement: `local-only` resource details must not be sent to external model prompts, and sensitive free-form alert, tool-result, investigation, and hosted-quickstart text must use the shared resource-policy redaction helper before leaving the local trust boundary. All provider-bound AI requests to non-local models must use the shared resource-policy sanitizer immediately before transport so later agentic turns cannot bypass the advertised handling posture.
|
||||
10. Keep the canonical and frontend-served privacy disclosures aligned with
|
||||
the actual AI transport boundary: BYOK must remain described as direct to
|
||||
the chosen provider, hosted Quickstart must remain described as transiting
|
||||
Pulse infrastructure, and both disclosures must state that governed
|
||||
resource details use resource-policy redaction before non-local model
|
||||
transport.
|
||||
|
||||
## Current State
|
||||
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ The telemetry implementation is in [`internal/telemetry/telemetry.go`](../intern
|
|||
|
||||
Pulse can make outbound connections when you enable specific features:
|
||||
|
||||
- **AI (BYOK)**: when AI features are configured with your own API key, Pulse sends only the context required for your request directly to the provider you chose (OpenAI, Anthropic, etc.). Requests do not transit Pulse infrastructure. See `docs/AI.md`.
|
||||
- **AI (Quickstart)**: when the Pulse-hosted Quickstart provider is selected, your chat request — including messages, system prompt, and tool definitions — is forwarded through `license.pulserelay.pro/v1/quickstart/patrol` to the underlying model provider. This path exists so eligible quickstart users can try AI without their own API key; it means requests transit Pulse infrastructure. To keep prompts off Pulse infrastructure, use a BYOK provider instead.
|
||||
- **AI (BYOK)**: when AI features are configured with your own API key, Pulse sends only the context required for your request directly to the provider you chose (OpenAI, Anthropic, etc.). Requests do not transit Pulse infrastructure. Before non-local model requests leave the instance, governed resource details use the same resource-policy redaction shown in Data Handling: local-only resource details are omitted from detailed prompt sections or replaced with policy-safe summaries, and known restricted resource identifiers are redacted where they appear in provider-bound context. See `docs/AI.md`.
|
||||
- **AI (Quickstart)**: when the Pulse-hosted Quickstart provider is selected, your chat request, including messages, system prompt, and tool definitions, is forwarded through `license.pulserelay.pro/v1/quickstart/patrol` to the underlying model provider. This path exists so eligible quickstart users can try AI without their own API key; it means requests transit Pulse infrastructure. The same resource-policy redaction is applied before the Quickstart request is sent, and the Quickstart proxy requires the runtime to mark the request as using that policy. To keep prompts off Pulse infrastructure entirely, use a BYOK provider instead.
|
||||
- **Relay / Remote Access**: when relay is enabled, Pulse connects to the configured relay endpoint to enable mobile access. See Settings → Remote Access.
|
||||
- **Update checks**: Pulse can check for new releases/updates (for example via GitHub release metadata) depending on your deployment and configuration.
|
||||
|
||||
|
|
|
|||
|
|
@ -125,8 +125,8 @@ export const AISettingsDialogs: Component<AISettingsDialogsProps> = (props) => {
|
|||
</p>
|
||||
<p class="mt-1 text-xs text-blue-800 dark:text-blue-200">
|
||||
Open the hosted quickstart handoff, or skip it and connect your own model
|
||||
provider below. Hosted quickstart routes prompts through Pulse
|
||||
infrastructure; BYOK providers go direct.
|
||||
provider below. Hosted quickstart routes policy-redacted prompts through
|
||||
Pulse infrastructure; BYOK providers go direct to your chosen provider.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ describe('settings architecture guardrails', () => {
|
|||
|
||||
it('keeps default self-hosted commercial copy opt-in from shared settings primitives', () => {
|
||||
expect(aiSettingsDialogsSource).toContain('Open hosted handoff');
|
||||
expect(aiSettingsDialogsSource).toContain('Hosted quickstart routes policy-redacted prompts');
|
||||
expect(aiSettingsDialogsSource).not.toContain('Start Trial');
|
||||
expect(aiSettingsDialogsSource).not.toContain('RELAY_ONBOARDING_TRIAL_STARTING_LABEL');
|
||||
expect(generalSettingsPanelSource).toContain('Disable local-only commercial events');
|
||||
|
|
|
|||
|
|
@ -75,4 +75,12 @@ describe('systemSettings store', () => {
|
|||
expect(privacyDoc).toContain('uses client IP addresses transiently for abuse/rate limiting');
|
||||
expect(privacyDoc).toContain('Reset ID');
|
||||
});
|
||||
|
||||
it('documents hosted quickstart transport and resource-policy redaction in the privacy doc', () => {
|
||||
const privacyDoc = readFileSync(path.join(repoRoot, 'docs', 'PRIVACY.md'), 'utf8');
|
||||
|
||||
expect(privacyDoc).toContain('requests transit Pulse infrastructure');
|
||||
expect(privacyDoc).toContain('resource-policy redaction is applied before the Quickstart request');
|
||||
expect(privacyDoc).toContain('To keep prompts off Pulse infrastructure entirely, use a BYOK provider');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -36,4 +36,19 @@ describe('quickstart copy contract', () => {
|
|||
);
|
||||
expect(pricingSpec).toMatch(/it is not a general hosted\s+chat entitlement/);
|
||||
});
|
||||
|
||||
it('keeps hosted quickstart privacy copy aligned with resource-policy redaction', () => {
|
||||
const privacy = readRepoFile('docs/PRIVACY.md');
|
||||
const publicPrivacy = readRepoFile('frontend-modern/public/docs/PRIVACY.md');
|
||||
const aiSettingsDialog = readRepoFile(
|
||||
'frontend-modern/src/components/Settings/AISettingsDialogs.tsx',
|
||||
);
|
||||
|
||||
for (const copy of [privacy, publicPrivacy]) {
|
||||
expect(copy).toContain('resource-policy redaction is applied before the Quickstart request');
|
||||
expect(copy).toContain('requests transit Pulse infrastructure');
|
||||
expect(copy).toContain('To keep prompts off Pulse infrastructure entirely, use a BYOK provider');
|
||||
}
|
||||
expect(aiSettingsDialog).toContain('Hosted quickstart routes policy-redacted prompts');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ REPORT = {
|
|||
},
|
||||
},
|
||||
"summary": {
|
||||
"lane_count": 17,
|
||||
"lane_count": 18,
|
||||
},
|
||||
"coverage_gaps": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class SubsystemLookupTest(unittest.TestCase):
|
|||
{"v6-rc-cut", "v6-rc-stabilization", "v6-ga-promotion", "v6-product-lane-expansion"},
|
||||
)
|
||||
self.assertEqual(result["scope"]["control_plane_repo"], "pulse")
|
||||
self.assertEqual(result["status_summary"]["lane_count"], 17)
|
||||
self.assertEqual(result["status_summary"]["lane_count"], 18)
|
||||
|
||||
file_entry = result["files"][0]
|
||||
matches = {match["subsystem"] for match in file_entry["matches"]}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue