← back

A private knowledge wiki that compiles into a public portfolio

live automationsecurity

Most of the useful reasoning behind a homelab change happens before the final configuration exists: alternatives, failed approaches, and the tradeoff that finally made a decision stick. A repository shows the implementation. A chat export often contains the explanation. I wanted to keep both useful without turning my private working notes into a public website.

I built a pipeline that compiles that material into a cited private wiki, then prepares selected projects for this Astro portfolio. This page is one of its outputs. The design adapts an existing knowledge-as-code approach; my work here is the personal implementation, the simplifications, and the publication workflow.

Updated October 6, 2026: the walkthrough now includes private sanitization, sealed inputs, shared agent skills, technical visuals, and the complete site handoff.

Keep the knowledge private and reviewable

The private repository holds source material, compiled pages, and the workflow instructions. The public repository holds the website and content deliberately selected for it. I considered keeping everything together and filtering pages with a visibility flag, but separating the repositories makes the transfer explicit. A submodule arrangement would add private repository references and operational complexity to the public side.

From evidence to a public story

  1. Retain conversations, code, and notes as private evidence.
  2. Ingest on a branch, compile cited wiki pages, and review the changes.
  3. Select a project, sanitize copies, and prepare a checked private draft.
  4. Review the exact article, visuals, and site changes for accuracy and disclosure.
  5. After approval and release authorization, transfer the reviewed files to the public site.

Checks support the human decision; they do not approve a release. The private evidence stays behind.

The diagram shows the intended review sequence. Separate repositories help organize access and disclosure, but they do not isolate an agent with access to both. Repository permissions and deployment settings still matter.

The wiki has three page types. A project describes a thing built. A decision records the options and why one was chosen. A concept explains knowledge that several projects can reuse. Markdown frontmatter carries the type, dates, tags, source references, visibility, and schema version; JSON schemas define the required shape.

Ingestion works under a topic key so later sources enrich the existing work. Each run starts on its own branch, writes claim-level citations, validates the pages, regenerates navigation, commits, and stops for review. Imported commands and agent instructions are evidence to interpret, never instructions to execute.

I also closed the vocabulary. Approved concept names, aliases, tags, and typed relationships live in YAML lists. The agent can propose additions; the vocabulary operation records them after approval. Aliases reduce naming drift, while a person still needs to catch two differently named concepts that mean the same thing. The validator cannot decide semantic overlap.

Share the workflow between agents

This started with Claude Code and now exposes the same six operations to Codex. The maintained skill folders are shared through relative symlinks, and AGENTS.md directs Codex to the common CLAUDE.md conventions. Updating a publication rule therefore updates one maintained procedure.

OperationResponsibility
ingestCompile sources into cited pages on a review branch.
askAnswer from the wiki with page citations.
lintReport contradictions, missing support, and stale knowledge.
indexRegenerate the catalog and backlinks.
publishPrepare a selected project for public review.
vocabRecord explicitly approved vocabulary changes.

The agent does the reading and writing that requires judgment. Scripts handle the catalog, backlinks, schemas, vocabulary checks, and scans. A generated index should copy the recorded facts consistently; asking a model to reconstruct it adds another opportunity to omit a page.

These shared instructions do not grant or restrict operating-system access. They make the workflow consistent across agents; tool permissions are a separate concern.

Capture the publication inputs

Publication starts from one project and its directly linked decisions and concepts. The helper resolves aliases and includes allowed typed relationships, but does not traverse the entire graph recursively. Broken references stop preparation. For this project, the selected evidence is the project page plus eleven linked pages.

The publish step reads compiled wiki evidence. It does not reopen transcripts to make a weak section more interesting. If the wiki lacks the implementation detail needed for a walkthrough, I improve that record separately, review the change, and prepare fresh inputs.

The prepare command validates the wiki and captures the full selected files, including their metadata. It creates unchanged originals and separate editable copies, records their SHA-256 hashes, and credential-scans the captured bytes. It refuses to reuse an existing destination.

That separation became necessary while publishing the network project. Legitimate internal addresses belonged in the private record, but the public disclosure rules correctly rejected them. Applying that policy before a private rewrite made preparation fail for the wrong reason. I added a sanitization stage with different checks on either side.

MaterialPolicy appliedPurpose
Captured private originalsPrivate credential policyBlock credentials while retaining useful operational evidence.
Sanitized input copiesPublic disclosure policyAlso reject configured patterns for private topology and identifiers.
Finished article, public assets, and built sitePublic disclosure policyCheck the material that will actually leave the private workspace.

Both policies use Gitleaks. The public policy adds disclosure rules to the credential checks; the private record does not need to be made less useful to pass a publication scan. Neither policy was weakened to accommodate the article.

Sanitize copies and seal them

Only the sanitization copies are edited. The canonical wiki and captured originals retain their evidence, including details that do not belong on a public page. Every selected page keeps a corresponding nonempty copy, so a difficult decision record cannot silently disappear from the input set.

I remove private source metadata, repository references, conversation identifiers, and unnecessary operational details. Descriptive roles replace real addresses, hostnames, account names, and device identifiers. The reasoning and attribution survive that edit, as do rejected alternatives and unfinished tests.

For example, an unresolved test should become a sentence such as “The physical recovery login has not been tested.” Removing a private marker must not turn that uncertainty into a claim of success. Sanitization changes what can be disclosed; it does not improve the strength of the evidence.

Two copies. Different jobs.

  1. Capture original wiki pages and corresponding editable copies; credential-scan the captured evidence.
  2. Sanitize only the editable copies, preserving decisions, attribution, and unfinished tests.
  3. Seal the sanitized inputs: compare original/current wiki hashes, apply disclosure checks, and record sanitized and policy hashes.
  4. Draft from the sealed sanitized copies. The original evidence remains private and unchanged.

The final article still needs an output check and human review. This explanation is not a live scan or an approval.

In this sequence, the original copies provide the comparison record; the sealed sanitized copies supply the drafting evidence. Both remain private.

The seal command checks the selected files and the original/current wiki hashes, repeats the credential scan on originals, and applies the public policy to sanitized inputs. Missing or extra files, symlinks, private references, and unresolved evidence markers block the stage. The seal records the sanitized file hashes and both scanner-policy hashes.

These are the three helper invocations in schematic form, run with the wiki’s tooling container. The uppercase arguments represent a project slug, a new directory inside private staging, and an article file outside the input bundle; they are not literal paths to copy:

python scripts/publication.py prepare PROJECT PRIVATE_INPUTS
# Sanitize the editable copies and compare them with the originals.
python scripts/publication.py seal PRIVATE_INPUTS
# Draft the article using only the sealed sanitized evidence.
python scripts/publication.py check PRIVATE_INPUTS ARTICLE

A seal records checked bytes and policies. It cannot establish that the rewrite is faithful, and its receipt explicitly leaves human review pending.

Write a walkthrough from the evidence

The default article format now follows the implementation sequence: what I configured, where it belongs, why I chose it, and how I checked its behavior. Supported settings, small examples, and configuration tables should give a reader enough detail to understand the work. Explanatory pseudocode is labeled so it cannot be mistaken for an actual device export.

The distinction between proposed, configured, and tested work stays visible. Confirmed temporary experiments outside an article’s scope are omitted from its prose, examples, and diagrams while remaining in the private record. Leaving something out of an article does not establish that it was rolled back.

Visuals follow the same evidence rules. I prefer editable Mermaid, SVG, or HTML diagrams that explain a relationship, a policy, or a recovery sequence. Relevant sanitized screenshots and real project photos are useful too. Decorative AI covers, generic 3D network scenes, and glowing hardware illustrations are excluded: an image should explain something about the work.

AI can help produce a technical diagram, but its labels and connections still need inspection. If a visual animates a flow, it must distinguish illustration from live telemetry or a verified test. Interactive visuals need keyboard controls, mobile and theme checks, reduced-motion behavior, pause controls for continuous motion, and readable explanations without JavaScript. The diagrams on this page let the reader explore the workflow; their motion is illustrative.

The public metadata is deliberately small: title, summary, date, tags, and status. Private source paths and unresolved wiki links do not belong in the article. The supported reasoning must make sense to a reader who cannot open the private evidence.

Check the article and the whole handoff

The final check verifies the selected sources, original and sanitized hashes, and scanner policies. It rescans the sanitized inputs and the actual article, then validates public metadata. Scanner errors and findings stop the stage; diagnostics withhold detected values. A clean input scan cannot cover text generated afterward, so every rewrite needs another output check.

The private receipt identifies the exact checked article. It does not automatically cover an accompanying image, diagram script, stylesheet, or route change. That was the other gap I closed: the handoff now records every new or modified site file and its SHA-256, alongside the check results and review status.

Change after checkingRequired next step
Wiki evidence or selected source membership changesPrepare a fresh bundle.
Sanitized inputs or scanner policies changeSeal again and renew draft review.
Article wording changesCheck the final article again and renew review.
Assets or site integration changeUpdate the handoff, rerun applicable scans/build/browser checks, and review those changes.

For preview, the procedure uses a private copy of the Astro site with its locked dependencies. Only the preview output is served on loopback. Evidence bundles, manifests, private diffs, prompts, and receipts stay outside that served output. Source and assets are scanned, the site is built, and the generated output is scanned too. Browser checks cover the rendered page and relevant visual controls.

Review includes the exact article, the diff against its previous version, and all associated visuals and integration changes. After approval, the checks are rerun and the same recorded bytes are transferred. A public commit or PR, push, and deployment still need authorization; a public PR already exposes its contents.

What is implemented and what remains

The implementation review recorded 33 passing regression tests, including real-scanner coverage of private topology passing the credential policy and failing the public policy until generalized. The recorded network-article release also passed its build, source/asset/output scans, and desktop/mobile browser checks before the reviewed transfer. Those are specific outcomes, not a guarantee about the next article.

The system remains small: manually invoked skills and deterministic helpers. The LangGraph state machine is still deferred. I also left out a vector search service, with roughly 150 pages recorded as a point to reconsider retrieval. That is a judgment call, not a measured capacity limit. Semantic duplicate detection and separate threat-model/runbook page types remain unbuilt.

The most useful improvement came from running a real publication through the workflow. Private knowledge needed to retain its detail, the public rewrite needed its own input stage, and review needed to cover everything the site would serve. I would make those three requirements explicit earlier in a new design.

Several limits remain. Hashes detect changed bytes; they do not establish truth, ownership, approval, or test completion. Scanner rules cannot identify every sensitive detail, and text scanning cannot establish that a raster image is safe. A private bundle also does not sandbox an unrestricted agent. Enforced isolation would need a fresh context and actual filesystem/tool restrictions.

Finally, local hooks and CI files do not establish remote branch protection or prove deployment succeeded. Those controls require separate configuration and verification. The private wiki is still sensitive, and accuracy, attribution, and disclosure still need a person to review them.


Drafts and technical diagrams are AI-assisted. I review the decisions, attribution, and technical claims. Schema checks, hashes, and scanning support that review; they do not prove that a described control was tested.