# Context disclosure gate

Version: 1.0
Updated: 2026-10-02
Method: https://suhailmohebi.com/notes/context-without-oversharing/

Purpose: give each audience the minimum context it needs to act correctly, and nothing that identifies, exposes or leaks.

Output: a classified context list, a public-safe task packet and a Pass or Hold verdict from the disclosure gate.

## Use when

You are about to put working context into an agent prompt, a rule file, an issue, a screenshot or a public page.

## Quick start

1. Name the audience, the artifact’s lifetime and the action it enables.
2. Sort every fact into one of four classes, then keep, transform or remove it by class.
3. Run the scan and the gate on the source and on the rendered result.

A clean scan means no known pattern matched; it never proves that nothing private remains.

## 1. Audience

> This artifact is for [this run only / the team / the public], will exist for [lifetime], and enables [action].

Treat every page, screenshot, report, preview and copied prompt as shareable. Ask “does the reader need this?”, not “is this secret?”.

## 2. Sort the context

| Class | What belongs here | Treatment | Your items |
|---|---|---|---|
| Public | Published interfaces, documented behaviour, public methods | Use when relevant and current |  |
| Project-internal | Unreleased plans, internal routes, operational history | Abstract the method; remove the identifiers |  |
| Secret | Credentials, tokens, private keys, protected endpoints | Never copy, paraphrase or expose |  |
| Personal | Contact details, private schedules, addresses, private conversations | Remove unless explicitly authorised for that audience |  |

## 3. Minimum sufficient context

Give the agent five things; cut any fact that would not change its decision:

- Outcome: what observable state must be true when it is done?
- Scope: which files, routes or surfaces may it touch?
- Constraints: what must not change?
- Evidence: which checks prove the outcome?
- Stops: what requires a report instead of improvisation?

## 4. Redaction transforms

| Kind | Transform | Before → after |
|---|---|---|
| Identity | person, client or project → role | “[name] at [client]” → “the service owner” |
| Exact values | number → range or placeholder | “p95 412 ms” → “p95 under half a second” |
| Paths and hosts | private → neutral placeholder | `/Users/<name>/<repo>` → `/work/app`; internal host → `app.example.com` |
| Credentials | none: remove | value → removed; rotate it if it was ever shared |

Use reserved names (`example.com`, `.test`, `.example`, `.invalid`) so placeholders cannot point at a real party. Noun–verb test: generalise nouns, identifiers and numbers; the verbs must still teach a complete workflow.

## 5. Public-safe task packet

```text
AUDIENCE
[This run only | Team | Public]. Treat the output as shareable.

OUTCOME
[Observable result, described without naming a private project.]

SCOPE
[Allowed files or generic surface types.]

CONSTRAINTS
[Behaviour and facts that must not change.]

SOURCE OF TRUTH
Use the approved source supplied for this run. Do not restate protected values in the output.

EXCLUSIONS
No names, contact details, credentials, local paths, private URLs, private metrics,
copied conversations or unreleased plans.

EVIDENCE
[Build, link check, rendered preview], then the disclosure scan and gate.

STOP IF
The result needs an excluded fact, or the source of truth conflicts with this packet.
```

Keep four layers apart, one owner per fact: public rules, private facts (loaded only when needed), task packet, public artifact.

## 6. Scan

Read-only; needs GNU or BSD grep (other greps can skip dotfiles such as `.env`). It never prints a matched value.

```bash
#!/usr/bin/env bash
# disclosure-scan.sh - flag likely secrets and private data before sharing.
# Usage: bash disclosure-scan.sh PATH [PATH...]   Prints label and file:line, never the match.
# Exit: 0 no match (not proof of absence), 1 findings to review, 2 the scan failed.
set -u
[ "$#" -gt 0 ] || { echo "usage: disclosure-scan.sh PATH [PATH...]" >&2; exit 2; }
case $(grep --version 2>/dev/null | head -n 1) in *GNU*|*BSD*) ;; *) echo "ERROR: needs GNU or BSD grep" >&2; exit 2 ;; esac
found=0
scan() {
  label=$1; regex=$2; shift 2
  hits=$(grep -rnHIE --exclude-dir=.git --regexp="$regex" -- "$@"); status=$?
  [ "$status" -le 1 ] || { echo "ERROR: scan failed ($label)" >&2; exit 2; }
  [ -n "$hits" ] || return 0
  found=1
  printf '%s\n' "$hits" | cut -d: -f1,2 | sed "s/^/[$label] /"
}
scan cloud-key   '(AKIA|ASIA)[A-Z0-9]{16}' "$@"
scan private-key '-----BEGIN [A-Z ]*PRIVATE KEY( BLOCK)?-----' "$@"
scan token       '(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_.-]{20,}|github_pat_[A-Za-z0-9_]{20,}|(xoxb|xoxp|xoxe|xapp|xwfp)-[A-Za-z0-9-]{10,}' "$@"
scan email       '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}' "$@"
scan ipv4        '(^|[^0-9.])([0-9]{1,3}\.){3}[0-9]{1,3}\.?([^0-9.]|$)' "$@"
scan home-path   '/(Users|home)/[A-Za-z0-9._-]+|[A-Za-z]:\\Users\\' "$@"
[ "$found" -eq 1 ] || echo "No pattern matched. That is not proof that nothing private remains."
exit "$found"
```

It cannot see names, phone numbers, paraphrased facts, secrets of unknown shape, binary files, text in images, or paths you did not pass. For more secret formats, add gitleaks (v8.19 or later): `gitleaks dir --redact -v PATH` for files, `gitleaks git --redact -v` for history (`detect` and `protect` are deprecated).

## 7. Disclosure gate

Check the source and the rendered result, including metadata and screenshots:

- [ ] No private organisation, project, product or person is named.
- [ ] No email address, phone number, location detail or private schedule.
- [ ] No local path, protected route, credential, token or configuration value.
- [ ] No private number or internal metric that could be generalised.
- [ ] Screenshots show no tabs, accounts, notifications, filenames or browser history.
- [ ] The lesson is still complete after removal: a stranger could apply it.
- [ ] Structured data, social metadata and generated navigation got the same review.

Verdict: Pass / Hold. Avoid both failures: oversharing the working context, and over-redacting away the method.

## Worked example

An internal incident note becomes a public method page.

| Fact | Class | Treatment |
|---|---|---|
| Client and project names | Project-internal | “a client site” |
| Pasted deploy log with a token | Secret | log removed; owner rotates the token |
| A teammate’s email in the credits | Personal | removed |
| Repository path in a command | Project-internal | `/work/site` |
| Inventory consumers, rebuild, verify the render, compare the deployed response | Public | kept: this is the method |

First scan of `draft/` and the rendered `public/`: `[token] draft/note.md:42`, `[email] draft/note.md:7`, `[home-path] draft/note.md:15`, exit 1. After the fixes the scan exits 0, but the gate returns Hold: a screenshot shows a browser tab with the client’s name. Cropped, it passes 7/7.

**Verdict:** Pass, published only after the owner confirmed the exposed token was rotated.

## Stop if

- The output needs an excluded fact to make sense: return it to the requester; do not paraphrase it.
- A secret reached a shared surface (prompt, log, draft, preview, commit history): treat it as exposed, even after a clean scan.
- The audience or the artifact’s lifetime is unknown.
- The scan failed (exit 2), or the rendered output and metadata were not reviewed.
- Removing identity leaves no usable method: publish nothing rather than a vague warning.

## Sources

- AWS: IAM identifiers, unique ID prefixes — https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html (checked 2026-10-02)
- GitHub Docs: GitHub’s token formats — https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github (checked 2026-10-02)
- Slack: Tokens — https://docs.slack.dev/authentication/tokens/ (checked 2026-10-02)
- Gitleaks: README — https://github.com/gitleaks/gitleaks (checked 2026-10-02)
- IETF: RFC 2606, Reserved Top Level DNS Names — https://www.rfc-editor.org/rfc/rfc2606.html (checked 2026-10-02)
