Align privacy guide checks with provider and telemetry boundaries

Keep the reviewed BYOK disclosures while testing their meaning across Markdown wrapping and UK spelling. Limit retired-offer checks to Pulse-hosted models, and retain explicit checks for direct provider traffic, restricted identifiers and local endpoint verification. Distinguish model context from pseudonymous usage telemetry without an ambiguous anonymity phrase.

Contract-Neutral: Existing help and its regression checks only; model transport, redaction, authorisation, retention and telemetry runtime are unchanged.
Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-10-31 10:01:36 +00:00
parent bd78c18481
commit 880900aed9
5 changed files with 29 additions and 12 deletions
+1 -1
View File
@@ -879,7 +879,7 @@ happens at the configured endpoint. With a hosted model, context travels directl
from a self-managed Pulse instance to that provider, not through Pulse
infrastructure.
- **Model context is not anonymous telemetry.** It can include resource names
- **Model context differs from usage telemetry.** It can include resource names
and addresses, monitoring state, relationships, operator notes and objectives,
prior findings and tool results used in the run. Review the chosen provider's
retention and training policies before enabling scheduled Patrol or an
+1 -1
View File
@@ -879,7 +879,7 @@ happens at the configured endpoint. With a hosted model, context travels directl
from a self-managed Pulse instance to that provider, not through Pulse
infrastructure.
- **Model context is not anonymous telemetry.** It can include resource names
- **Model context differs from usage telemetry.** It can include resource names
and addresses, monitoring state, relationships, operator notes and objectives,
prior findings and tool results used in the run. Review the chosen provider's
retention and training policies before enabling scheduled Patrol or an
@@ -110,6 +110,7 @@ describe('systemSettings store', () => {
path.join(frontendRoot, 'public', 'docs', 'PRIVACY.md'),
'utf8',
);
const privacyText = privacyDoc.replace(/\s+/g, ' ');
expect(privacyDoc).not.toContain('secure remote web access');
expect(privacyDoc).toContain('Relay does not provide remote access to the web UI');
@@ -124,8 +125,8 @@ describe('systemSettings store', () => {
expect(privacyDoc).toContain('uses request IP addresses transiently for abuse/rate limiting');
expect(privacyDoc).toContain('Reset ID');
expect(privacyDoc).toContain('active Patrol objective briefs');
expect(privacyDoc).toContain('encrypted at rest in the local organization data directory');
expect(privacyDoc).toContain('objective text is not included in Pulse usage telemetry');
expect(privacyText).toMatch(/encrypted at rest in the local organi[sz]ation data directory/);
expect(privacyText).toContain('objective text is not included in Pulse usage telemetry');
expect(privacyDoc).toContain('Pulse Intelligence Patrol control completed operations loop 30d');
expect(privacyDoc).toContain(
'Pulse Intelligence Patrol control paid resolved operations loop 30d',
@@ -169,13 +170,19 @@ describe('systemSettings store', () => {
it('documents self-hosted AI provider transport and resource-policy redaction in the privacy doc', () => {
const privacyDoc = readFileSync(path.join(repoRoot, 'docs', 'PRIVACY.md'), 'utf8');
const privacyText = privacyDoc.replace(/\s+/g, ' ');
expect(privacyDoc).toContain(
'AI prompts from self-managed installs do not transit Pulse infrastructure',
expect(privacyText).toContain(
'providers receive this context directly from your self-managed Pulse instance',
);
expect(privacyDoc).toContain(
'governed resource details use the same resource-policy redaction',
expect(privacyText).toContain('AI prompts do not transit Pulse infrastructure');
expect(privacyText).toContain('Pulse applies secret filtering and resource-policy handling');
expect(privacyText).toContain('known restricted resource identifiers are redacted');
expect(privacyText).toContain(
'Internal and Sensitive resources can still be shared with a hosted model',
);
expect(privacyText).toContain(
'verify that the chosen endpoint runs within your trusted network and does not forward requests elsewhere',
);
expect(privacyDoc).toContain('Local providers stay on your network');
});
});
@@ -7,7 +7,17 @@ const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../../../../'
const readRepoFile = (relativePath: string) =>
readFileSync(resolve(repoRoot, relativePath), 'utf-8');
// Provider privacy disclosures must be able to describe remote models. This
// guard concerns the retired Pulse-hosted offering, not an operator's provider.
const pulseHostedOffering = /Pulse[- ]hosted (?:AI|models?)/i;
describe('quickstart copy contract', () => {
it('distinguishes provider privacy disclosures from a Pulse-hosted offering', () => {
expect('a hosted model receives provider-bound context').not.toMatch(pulseHostedOffering);
expect('Pulse-hosted AI with no API key').toMatch(pulseHostedOffering);
expect('Pulse-hosted model').toMatch(pulseHostedOffering);
});
it('keeps self-hosted public docs free of hosted quickstart claims', () => {
const readme = readRepoFile('README.md');
const pulsePro = readRepoFile('docs/PULSE_PRO.md');
@@ -34,8 +44,7 @@ describe('quickstart copy contract', () => {
]) {
expect(copy).not.toMatch(/quickstart/i);
expect(copy).not.toContain('quickstart:pulse-hosted');
expect(copy).not.toMatch(/hosted AI/i);
expect(copy).not.toMatch(/hosted model/i);
expect(copy).not.toMatch(pulseHostedOffering);
expect(copy).not.toMatch(/hosted[\s\S]{0,120}no API key/i);
expect(copy).not.toMatch(/Pulse-hosted[\s\S]{0,120}no API key/i);
expect(copy).not.toMatch(/Pulse Account[\s\S]{0,120}no API key/i);
+2 -1
View File
@@ -802,7 +802,8 @@ func TestTelemetryPrivacyDocsKeepObserverProposalContentLocal(t *testing.T) {
if err != nil {
t.Fatalf("read %s: %v", relativePath, err)
}
content := string(raw)
// Markdown wrapping must not change the required privacy disclosures.
content := strings.Join(strings.Fields(string(raw)), " ")
for _, required := range []string{
"model-authored observer proposal",
"encrypts that artifact with the retained objective",