Skip to content

feat(security): integrate trust context policy with global read roots and channel audiences - #387

Merged
Aaronontheweb merged 3 commits into
devfrom
feat/trust-context-integration
Mar 23, 2026
Merged

feat(security): integrate trust context policy with global read roots and channel audiences#387
Aaronontheweb merged 3 commits into
devfrom
feat/trust-context-integration

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Collaborator

Summary

  • Adds GlobalReadRoots to ToolAudienceProfiles with {skills_dir} and {identity_dir} tokens — skills and identity files are now readable regardless of audience profile, unblocking skill loading under Team/Public audiences
  • Adds ChannelAudiences dictionary to SlackChannelOptions for per-channel audience overrides (resolution: explicit channel ID → "dm" key → existing heuristic fallback)
  • Adds Security section to config schema (DeploymentPosture, ShellExecutionMode, StrictDefaults)
  • Init wizard now emits Security section and Slack.ChannelAudiences with smart defaults derived from deployment posture
  • Escalates missing Tools section from Warning → Error in doctor check
  • Adds SecurityPolicyDoctorCheck (missing Security → Error; null posture with relaxed defaults → Error)

Context

PRs #380 (memory quality overhaul) and #249 (trust context policy) both merged to dev, but the system was broken: Slack sessions default to Team audience with no Tools config section, blocking shell_execute, restricting file_read to session directory (can't load skills), and causing empty response loops.

Test plan

  • dotnet build — 0 errors, 0 warnings
  • dotnet test — 1,311 tests pass (0 failures)
  • dotnet slopwatch analyze — 0 violations
  • netclaw init generates Security + Tools + ChannelAudiences
  • netclaw doctor passes with complete config, fails without Security/Tools
  • Slack DM → Personal → shell_execute works, skills loadable
  • Slack channel → Team → shell_execute blocked, skills readable via global roots

…, channel audiences, and doctor checks

Unblocks Slack sessions that were stuck in empty response loops due to
Team audience defaulting to session-only file access (blocking skill
loading) and missing Tools/Security config sections.

- Add GlobalReadRoots to ToolAudienceProfiles with {skills_dir} and
  {identity_dir} tokens so skills and identity files are readable
  regardless of audience profile
- Add ChannelAudiences dictionary to SlackChannelOptions for per-channel
  audience overrides (explicit channel ID → "dm" key → heuristic fallback)
- Add Security section to config schema (DeploymentPosture,
  ShellExecutionMode, StrictDefaults)
- Init wizard now emits Security section and ChannelAudiences with smart
  defaults derived from deployment posture
- Escalate missing Tools section from Warning → Error in doctor check
- Add SecurityPolicyDoctorCheck (missing Security → Error, null posture
  with relaxed defaults → Error)
- Make CreateProfiles() explicitly set GlobalReadRoots (fragile initializer)
- Extract shared ResolvePathToken() in ToolAudienceProfileResolver to
  eliminate duplicated token matching for {skills_dir}/{identity_dir}
- Extract ResolveAndMergeRoots() in ScopedFileAccessPolicy to eliminate
  duplicated global-read-root merge logic
- Use StringComparer.Ordinal for ChannelAudiences (Slack IDs are case-sensitive)
- Add test: DM channel ID takes precedence over "dm" key
- Add test: invalid audience value falls through to heuristic
- Pin exact severity in SecurityPolicyDoctorCheck missing-config test
- Add clarifying comment for channel audience defaults (channels always Team)
…dRoots literal path bug

- Hard fail when a ChannelAudiences key matches but the value is not a
  recognized audience string — a typo like "persoanl" now denies the
  message instead of silently degrading to the heuristic fallback
- Fix ResolveGlobalReadRoots skipping literal absolute paths when
  NetclawPaths is not injected (early return on null _paths)
- Cache resolved global read roots in ScopedFileAccessPolicy to avoid
  re-resolving config-static paths on every file access
- Align InitWizardViewModel.ChannelAudiences comparer to Ordinal,
  matching SlackChannelOptions runtime behavior
- Broaden CLAUDE.md silent fallback rule to a general principle
- Add tests for PopulateChannelAudiences, literal GlobalReadRoots,
  and invalid audience value denial
@Aaronontheweb
Aaronontheweb marked this pull request as ready for review March 23, 2026 15:02
@Aaronontheweb
Aaronontheweb merged commit 0944fa2 into dev Mar 23, 2026
3 checks passed
@Aaronontheweb
Aaronontheweb deleted the feat/trust-context-integration branch March 23, 2026 18:54
@Aaronontheweb Aaronontheweb mentioned this pull request Mar 25, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant