Zion Boggan · April 2026 · Oversight Protocol v0.4.5

v0.4.5 introduced a Tkinter desktop starter for users who are not comfortable at the command line. The GUI wraps the three first-contact workflows every issuer and recipient needs: generate an identity, seal a file to a recipient, and open a sealed file. The code is a thin adapter over the oversight_core library; everything it can do is also available from the CLI. The GUI is a stepping stone toward the web viewer tracked on the roadmap, not the final launch surface.

Installation

Tkinter ships with CPython on Windows and macOS. On Debian, Ubuntu, and derivatives it is packaged separately as python3-tk. Verify that import succeeds before running the GUI:

python -c "import tkinter; print(tkinter.TkVersion)"

Install Oversight from the repository in editable mode, which registers the oversight CLI and the oversight-gui entry point:

git clone https://github.com/oversight-protocol/oversight
cd oversight
pip install -e . --user

No additional GUI dependency is required beyond Tkinter. The GUI uses only modules from the standard library plus oversight_core itself.

Launching the GUI

Two equivalent invocations:

oversight gui       # subcommand on the main CLI
oversight-gui       # dedicated entry point installed by pip

Both resolve to cli.gui:main. A single Tkinter window opens at 760 by 540 pixels with three tabs: Generate Keys, Seal File, and Open File. Closing the window exits the process.

Tab 1: Generate Keys

Use this tab to create a new Oversight identity for an issuer or recipient. The identity consists of an X25519 keypair for encryption and an Ed25519 keypair for signing.

FieldDescription
Identity nameHuman-readable identifier stored inside the key JSON. Defaults to alice. Any string is accepted.
Private key outputPath where the private identity file will be written. Use Choose Output to select a location with the native save dialog.

Pressing Generate Keypair writes two files next to each other:

Tab 2: Seal File

Use this tab to seal a plaintext file to a named recipient. The GUI mirrors the CLI seal semantics: canonical content hash, L3 safety policy, optional L1 and L2 watermarks, passive beacons, and a content fingerprint sidecar are all produced automatically.

FieldDescription
Input filePath to the plaintext to seal.
Issuer private keyPath to the issuer's private identity JSON (the file produced by the Generate Keys tab for the issuer).
Recipient public keyPath to the recipient's .pub.json file.
Sealed outputWhere to write the .sealed container. If left blank the GUI uses <input>.sealed.
Registry URLRegistry endpoint recorded in the manifest's policy block. Defaults to https://registry.oversightprotocol.dev. No network call is made from the GUI at seal time; the URL is stored for later open policy checks.
Content typeMIME type recorded in the manifest. Defaults to text/plain. The content type also informs L3 document-class inference.
L3 modeDropdown with auto, off, boilerplate, full. auto picks the safest mode for the detected document class: full L3 for prose, boilerplate-only for legal or regulatory documents, and off for source code, SQL, logs, and structured data.
Embed L1/L2 watermarksCheckbox, on by default. L1 (zero-width Unicode) and L2 (trailing whitespace) do not change visible bytes, so they are safe for every document class. Disabling this checkbox seals the file without any watermarks.

L3 disclosure prompt

When the selected L3 mode, document class, and content produce a decision that would rewrite body text, the GUI pops a disclosure dialog before proceeding:

L3 semantic watermarking changes visible prose. Continue?

Dismissing the dialog aborts the seal. Confirming applies the L3 transformation, then embeds L2 and L1 on top of the L3-modified text. This matches the CLI's --l3-ack gate: the acknowledgement is a structural step, not a checkbox you forget about. The decision (mode, document class, ack) is recorded in the signed manifest under l3_policy.

What the GUI writes

The manifest also carries a canonical_content_hash, which is a SHA-256 of the pre-watermark plaintext. If a dispute later turns on whether the recipient received the exact text of the canonical source, this hash is the anchor the comparison runs against.

Tab 3: Open File

Use this tab to decrypt a sealed file with the recipient's private identity. The GUI verifies the manifest signature, enforces policy (time windows, max_opens, jurisdiction), unwraps the DEK, AEAD-decrypts the ciphertext, and checks the content hash before writing the plaintext to disk.

FieldDescription
Sealed filePath to the .sealed container.
Recipient private keyPath to the recipient's private identity JSON.
Plaintext outputWhere the decrypted plaintext should be written.

Policy or signature failures surface as a Tkinter error dialog; successful opens show a small confirmation dialog. The GUI does not print per-layer watermark diagnostics the way the CLI does. For forensic attribution work, use oversight attribute on the command line; the GUI is only for the legitimate recipient workflow.

Troubleshooting

SymptomCause and fix
ModuleNotFoundError: No module named 'tkinter' Tkinter is not installed. On Debian or Ubuntu: sudo apt install python3-tk. On Fedora: sudo dnf install python3-tkinter. On Windows and macOS Tkinter ships with the CPython installer.
GUI launches but oversight is not found The package was installed but its scripts directory is not on PATH. Run python -m pip show -f oversight-core | grep bin to locate it, or invoke with python -m cli.gui.
Seal dialog reports that the file is not UTF-8 text The input is binary or not valid UTF-8. Watermarking is defined only over UTF-8 plaintext. Uncheck Embed L1/L2 watermarks to seal without marks, or use the appropriate format adapter from the CLI.
Output path is refused as private key material The GUI detected an Oversight private identity JSON at the output path. Choose a different destination; seal and open never overwrite private keys.
Open dialog reports PolicyViolation The manifest's policy constraints (time window, max_opens, jurisdiction) rejected the attempt. Inspect the manifest with oversight inspect to see which constraint applies.

Implementation Notes

The GUI is implemented as a single file, cli/gui.py (212 lines), and consists of one tk.Tk subclass, OversightGui, with a ttk.Notebook containing three frames. Each frame is built by a _build_* method and holds its own field variables. The entry point registered in pyproject.toml is oversight-gui = "cli.gui:main", and oversight gui resolves to the same main() function through the main CLI's subparser.

Dependencies

Private key hardening

_write_private_json() uses os.open() with O_WRONLY | O_CREAT | O_TRUNC and mode 0o600 on POSIX so new private key files are created with restrictive permissions from the start rather than relaxed and then tightened. On Windows the helper writes the file normally; protect the enclosing directory with an ACL if the host is shared. This is the same hardening pass that was applied to the CLI seal path in the v0.4.4 security cycle.

Window sizing and layout

The window is fixed at 760 by 540 pixels. Each tab uses a ttk.Frame with a grid layout where column 1 expands on window resize so the file-path entries grow with the window. Browse buttons call tkinter.filedialog.askopenfilename() or asksaveasfilename() and write the chosen path into the entry's StringVar.

Scope and non-goals

The Tkinter starter is intentionally small. Features deliberately left out of v0.4.5 include: per-phase attribution diagnostics (use the CLI), registry federation views, hardware-key integration (planned alongside the Rust KeyProvider trait), multi-recipient sealing (disabled protocol-wide until the manifest can honestly bind every recipient), and the drag-and-drop share workflow planned for the web viewer.

If you need any of those, stay on the CLI for now. The roadmap at docs/roadmap.html tracks the web viewer, Outlook add-in, and the broader launch sequence.