.spec/ is untracked and exists on one disk #23

Open
opened 2026-09-01 16:58:31 +00:00 by jlxq0 · 4 comments
Owner

.spec/BUILD_SPEC.md (635 lines), .spec/DEPLOY_SPEC.md (766) and .spec/TOOLS.md (239)
are excluded by .gitignore and exist only in the ~/Code/jlxq0/typst-mcp checkout. The
Forge worktrees do not have them.

HANDOFF.md described them as "not reconstructable from tracked files" and that file is
being deleted, so without this issue the only written record that they exist and are
irreplaceable goes with it.

GOAL.md §8 and Plan.md's header both named them as the specification source, so a reader
of either was being pointed at something their checkout did not contain.

Why they are not simply committed

Committing them publishes them, because of #22. They were grepped: no secret values, but
they name the 1Password vault and item, the registry credential item, the secret store and
the cluster, which is the same class of content already exposed there.

What to do, once #22 is settled

If the repository ends up genuinely private, commit them. If it stays public, either
sanitize them first or move their content into issues. Either way they should not remain a
single untracked copy on one laptop that a disk failure or a tidy-up ends.

Blocked on #22.

`.spec/BUILD_SPEC.md` (635 lines), `.spec/DEPLOY_SPEC.md` (766) and `.spec/TOOLS.md` (239) are excluded by `.gitignore` and exist only in the `~/Code/jlxq0/typst-mcp` checkout. The Forge worktrees do not have them. `HANDOFF.md` described them as **"not reconstructable from tracked files"** and that file is being deleted, so without this issue the only written record that they exist and are irreplaceable goes with it. `GOAL.md` §8 and `Plan.md`'s header both named them as the specification source, so a reader of either was being pointed at something their checkout did not contain. ## Why they are not simply committed Committing them publishes them, because of #22. They were grepped: no secret values, but they name the 1Password vault and item, the registry credential item, the secret store and the cluster, which is the same class of content already exposed there. ## What to do, once #22 is settled If the repository ends up genuinely private, commit them. If it stays public, either sanitize them first or move their content into issues. Either way they should not remain a single untracked copy on one laptop that a disk failure or a tidy-up ends. Blocked on #22.
Author
Owner

The block is gone. The question it was blocking is now the live one.

jlxq0/typst-mcp became public on Forge at 2026-09-01T23:49:16Z, so both sides are public
and nothing mechanically prevents committing .spec/. See #22.

Not committing it yet, because the block being removed is not the same as the condition
being met. This issue recorded two branches:

If the repository ends up genuinely private, commit them. If it stays public, either
sanitize them first or move their content into issues.

It stayed public, which is the branch that says sanitize first. And the intent relayed
at the time the flip was expected was public on both once sanitized, so committing the
unsanitized directory would be doing the thing in the wrong order rather than early.

What a sanitize decision has to weigh

The scan is on #22 and it found no secret values in .spec/: 0 Bearer literals, 0 JWTs,
0 PEM keys, 0 private IPs, 0 long base64 assignments. One op:// occurrence and it is a
reference path in a runbook command, op read 'op://Oddie Apps/typst-mcp-www/…', which is
the correct pattern and carries no value.

What it names: clusters/fondue ×16, typst-mcp-www ×9, Oddie Apps ×6,
onepassword-hanso ×5, kampong.social ×4, matrix-mcp-www ×3, config-fondue ×3,
Gruyere ×2, one Entra app id each.

Every one of those categories is already public in AGENTS.md on this repository's
main.
So committing .spec/ as-is adds volume rather than a class, and sanitizing it
without also sanitizing AGENTS.md would protect nothing. Under the standing ruling,
GitOps paths and the cluster name in operational prose stay regardless.

That makes the real question narrower than "sanitize .spec/": it is whether the
1Password store, vault and item names should be public anywhere in this repository. That is
one decision covering both files, and it is not mine.

Meanwhile the original risk is unchanged

1,640 lines, one untracked copy, one disk, no second copy. A disk failure or a tidy-up still
ends it. That risk was the reason this issue exists and removing the block did not reduce
it.

## The block is gone. The question it was blocking is now the live one. `jlxq0/typst-mcp` became public on Forge at `2026-09-01T23:49:16Z`, so both sides are public and nothing mechanically prevents committing `.spec/`. See #22. **Not committing it yet**, because the block being removed is not the same as the condition being met. This issue recorded two branches: > If the repository ends up genuinely private, commit them. If it stays public, either > sanitize them first or move their content into issues. It stayed public, which is the branch that says **sanitize first**. And the intent relayed at the time the flip was expected was *public on both **once sanitized***, so committing the unsanitized directory would be doing the thing in the wrong order rather than early. ## What a sanitize decision has to weigh The scan is on #22 and it found **no secret values** in `.spec/`: 0 Bearer literals, 0 JWTs, 0 PEM keys, 0 private IPs, 0 long base64 assignments. One `op://` occurrence and it is a reference path in a runbook command, `op read 'op://Oddie Apps/typst-mcp-www/…'`, which is the correct pattern and carries no value. What it names: `clusters/fondue` ×16, `typst-mcp-www` ×9, `Oddie Apps` ×6, `onepassword-hanso` ×5, `kampong.social` ×4, `matrix-mcp-www` ×3, `config-fondue` ×3, `Gruyere` ×2, one Entra app id each. **Every one of those categories is already public in `AGENTS.md` on this repository's `main`.** So committing `.spec/` as-is adds volume rather than a class, and sanitizing it without also sanitizing `AGENTS.md` would protect nothing. Under the standing ruling, GitOps paths and the cluster name in operational prose stay regardless. That makes the real question narrower than "sanitize `.spec/`": it is whether the 1Password store, vault and item names should be public anywhere in this repository. That is one decision covering both files, and it is not mine. ## Meanwhile the original risk is unchanged 1,640 lines, one untracked copy, one disk, no second copy. A disk failure or a tidy-up still ends it. **That risk was the reason this issue exists and removing the block did not reduce it.**
Author
Owner

The estate sweep strengthens the reason to hold, and changes what holding means

AGENTS.md no longer names the 1Password store, either vault, or any item: removed at
123d55b, verified gone from both served copies with a control.

That inverts the argument I made earlier on this issue. I had said committing .spec/
as-is "adds volume rather than a class, and sanitizing it without also sanitizing
AGENTS.md would protect nothing"
. AGENTS.md is now sanitized, so that is no longer
true.
Committing the directory unmodified would reintroduce the class this repository
has just stopped carrying, and it would do it as the only file in a 21-repository public
estate that names a store, a vault or an item.

The .spec/ figures from the scan on #22, unchanged: clusters/fondue ×16,
typst-mcp-www ×9, Oddie Apps ×6, onepassword-hanso ×5, kampong.social ×4,
matrix-mcp-www ×3, config-fondue ×3, Gruyere ×2, one Entra app id each. No secret
values, and its one op:// occurrence is a reference path in a runbook command.

Under the standing ruling the clusters/fondue paths and the cluster name stay. The store,
vault and item names are the part now without precedent in this repository.

So the shape of the fix is settled even though the decision is not

Sanitize the same way AGENTS.md was: not by redacting names, but by replacing the
enumerations with the command that answers them from the cluster.
That was the better
document either way, independently of who can read it, because a file cannot go stale and
kubectl cannot be wrong. DEPLOY_SPEC.md is a runbook, which is exactly the kind of
document that should be reading the live system rather than restating it.

That is a real edit to 766 lines rather than a delete-and-commit, which is why it is not
done here and now.

What has not changed

1,640 lines, one untracked copy, one disk, no second copy. A disk failure or a tidy-up
still ends it. Every hour this stays open, that is the risk, and neither the repository
going public nor AGENTS.md being cleaned has reduced it by anything.

## The estate sweep strengthens the reason to hold, and changes what holding means `AGENTS.md` no longer names the 1Password store, either vault, or any item: removed at `123d55b`, verified gone from both served copies with a control. That inverts the argument I made earlier on this issue. I had said committing `.spec/` as-is *"adds volume rather than a class, and sanitizing it without also sanitizing `AGENTS.md` would protect nothing"*. **`AGENTS.md` is now sanitized, so that is no longer true.** Committing the directory unmodified would **reintroduce** the class this repository has just stopped carrying, and it would do it as the only file in a 21-repository public estate that names a store, a vault or an item. The `.spec/` figures from the scan on #22, unchanged: `clusters/fondue` ×16, `typst-mcp-www` ×9, `Oddie Apps` ×6, `onepassword-hanso` ×5, `kampong.social` ×4, `matrix-mcp-www` ×3, `config-fondue` ×3, `Gruyere` ×2, one Entra app id each. No secret values, and its one `op://` occurrence is a reference path in a runbook command. Under the standing ruling the `clusters/fondue` paths and the cluster name stay. The store, vault and item names are the part now without precedent in this repository. ## So the shape of the fix is settled even though the decision is not Sanitize the same way `AGENTS.md` was: **not by redacting names, but by replacing the enumerations with the command that answers them from the cluster.** That was the better document either way, independently of who can read it, because a file cannot go stale and `kubectl` cannot be wrong. `DEPLOY_SPEC.md` is a runbook, which is exactly the kind of document that should be reading the live system rather than restating it. That is a real edit to 766 lines rather than a delete-and-commit, which is why it is not done here and now. ## What has not changed **1,640 lines, one untracked copy, one disk, no second copy.** A disk failure or a tidy-up still ends it. Every hour this stays open, that is the risk, and neither the repository going public nor `AGENTS.md` being cleaned has reduced it by anything.
Author
Owner

Answered by Julian in Matrix on 2026-09-02, event $kBQH2qSrcaDHP_Rti5xTxdz-epM95l1cS1NlHUZDbmY.

He answered "You decide", so: A, sanitise and commit.

The reasoning, since it is mine rather than his

B does not reduce exposure. Issues on a public repository are public, so moving 1,640 lines into them publishes the same content in a worse container: no version history, no diff, and a specification split across three issues that the code cannot be read beside.

A does reduce it, and that is the whole value of the sanitising step. Rotation was declined on #22, so the class of content already exposed stays exposed. What must not go in is anything new and specific: the 1Password vault and item names, the registry credential item, the secret store and the cluster. Those become references to where the value lives rather than the identifiers themselves.

And A is the only option that ends the actual risk this issue names, which is not exposure at all: .spec/BUILD_SPEC.md (635 lines), DEPLOY_SPEC.md (766) and TOOLS.md (239) exist as a single untracked copy in one checkout, described as not reconstructable, and a disk failure or a tidy-up ends them.

What lands

The three files, sanitised, committed to jlxq0/typst-mcp. GOAL.md §8 and Plan.md pointed readers at them, so whatever survives of those should point at the tracked path instead of at something a checkout does not contain.

Unblocked by #22 closing.

Answered by Julian in Matrix on 2026-09-02, event `$kBQH2qSrcaDHP_Rti5xTxdz-epM95l1cS1NlHUZDbmY`. He answered *"You decide"*, so: **A, sanitise and commit.** ## The reasoning, since it is mine rather than his **B does not reduce exposure.** Issues on a public repository are public, so moving 1,640 lines into them publishes the same content in a worse container: no version history, no diff, and a specification split across three issues that the code cannot be read beside. **A does reduce it, and that is the whole value of the sanitising step.** Rotation was declined on `#22`, so the class of content already exposed stays exposed. What must not go in is anything *new* and specific: the 1Password vault and item names, the registry credential item, the secret store and the cluster. Those become references to where the value lives rather than the identifiers themselves. **And A is the only option that ends the actual risk this issue names**, which is not exposure at all: `.spec/BUILD_SPEC.md` (635 lines), `DEPLOY_SPEC.md` (766) and `TOOLS.md` (239) exist as a single untracked copy in one checkout, described as not reconstructable, and a disk failure or a tidy-up ends them. ## What lands The three files, sanitised, committed to `jlxq0/typst-mcp`. `GOAL.md` §8 and `Plan.md` pointed readers at them, so whatever survives of those should point at the tracked path instead of at something a checkout does not contain. Unblocked by `#22` closing.
Author
Owner

This is not waiting on Julian. Label removed.

#22 closed on 2026-09-02T00:25:56Z with both its questions answered by him:

  • make the Forge repo public (Matrix, 2026-08-30, event $GlA0nkHPx6smixhg…)
  • rotation: no, SIGNING_SECRET and TENANT_SALT stay (Matrix, 2026-09-02, event
    $kBQH2qSrcaDHP…)

That was the blocker, and nothing on this issue needs a decision from him now. What is
left is work, not a question
, and holding a waiting-on-julian label on it puts an item
on a list he has said is too long, for something nobody is waiting on him for.

What is actually left, and it is mine

Sanitize .spec/ the way AGENTS.md was sanitized in #26: replace the enumerations with
the commands that answer them from the cluster
, rather than redacting names.
DEPLOY_SPEC.md is a runbook, so it is exactly the document that should read the live
system instead of restating it, and that is the better file independently of who can read
it. A real edit across 766 lines.

Then remove .gitignore:35 and commit, which ends the thing this issue was filed about:
1,640 lines, one untracked copy, one disk, no second copy. Unchanged since the day it was
filed, and neither the repository going public nor AGENTS.md being cleaned reduced it.

The label removal itself needed doing twice, and that is worth recording

DELETE /issues/23/labels/waiting-on-julian returned 204 and removed nothing.
DELETE /issues/23/labels/1591 returned 204 and removed it. Same status code, opposite
outcomes, read back both times:

before          labels: [('waiting-on-julian', 1591)]
delete by name  HTTP 204   labels: [('waiting-on-julian', 1591)]   <- unchanged
delete by id    HTTP 204   labels: NONE

This repository had two labels of that name: 1350 from bin/fleet-ledger.sh and
1591 which I created on 2026-08-26 after GET /labels returned an empty list. Both
behaviours were correct and neither could see the other. 1591 is now deleted, nothing
carried it, and 1350 survives because the ledger recreates it by name.

Remove labels by id and read them back. 204 is the documented success code with no body,
so the call cannot distinguish removed from not found and reports success either way.
Found by alan across the fleet; reproduced here.

## This is not waiting on Julian. Label removed. #22 closed on 2026-09-02T00:25:56Z with both its questions answered by him: - **make the Forge repo public** (Matrix, 2026-08-30, event `$GlA0nkHPx6smixhg…`) - **rotation: no**, `SIGNING_SECRET` and `TENANT_SALT` stay (Matrix, 2026-09-02, event `$kBQH2qSrcaDHP…`) That was the blocker, and nothing on this issue needs a decision from him now. **What is left is work, not a question**, and holding a `waiting-on-julian` label on it puts an item on a list he has said is too long, for something nobody is waiting on him for. ## What is actually left, and it is mine Sanitize `.spec/` the way `AGENTS.md` was sanitized in #26: **replace the enumerations with the commands that answer them from the cluster**, rather than redacting names. `DEPLOY_SPEC.md` is a runbook, so it is exactly the document that should read the live system instead of restating it, and that is the better file independently of who can read it. A real edit across 766 lines. Then remove `.gitignore:35` and commit, which ends the thing this issue was filed about: 1,640 lines, one untracked copy, one disk, no second copy. **Unchanged since the day it was filed, and neither the repository going public nor `AGENTS.md` being cleaned reduced it.** ## The label removal itself needed doing twice, and that is worth recording `DELETE /issues/23/labels/waiting-on-julian` returned **204 and removed nothing**. `DELETE /issues/23/labels/1591` returned **204 and removed it**. Same status code, opposite outcomes, read back both times: before labels: [('waiting-on-julian', 1591)] delete by name HTTP 204 labels: [('waiting-on-julian', 1591)] <- unchanged delete by id HTTP 204 labels: NONE This repository had **two** labels of that name: `1350` from `bin/fleet-ledger.sh` and `1591` which I created on 2026-08-26 after `GET /labels` returned an empty list. Both behaviours were correct and neither could see the other. `1591` is now deleted, nothing carried it, and `1350` survives because the ledger recreates it by name. **Remove labels by id and read them back.** 204 is the documented success code with no body, so the call cannot distinguish *removed* from *not found* and reports success either way. Found by `alan` across the fleet; reproduced here.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jlxq0/typst-mcp#23
No description provided.