<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Diaryx</title>
  <link href="https://main.diaryx.org/diaryx/" rel="alternate"/>
  <link href="https://main.diaryx.org/diaryx/feed.xml" rel="self"/>
  <id>https://main.diaryx.org/diaryx/</id>
  <updated>2026-09-09T16:08:55Z</updated>
  <subtitle>Diaryx is a journal, personal archive, and website-maker in one. Your vault reads like a shelf of books, keeps its files the way professional archivists keep theirs, and publishes to circles of people you choose — who can write back in the margin.</subtitle>
  <entry>
    <title>PHILOSOPHY</title>
    <link href="https://main.diaryx.org/diaryx/docs/PHILOSOPHY.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/docs/PHILOSOPHY.html</id>
    <published>2026-09-09T16:08:55Z</published>
    <updated>2026-09-09T16:08:55Z</updated>
    <summary>Diaryx is inspired by the Joseph Smith Papers Project, which is described on its website as:

an effort to gather together all extant Joseph Smith documents and to publish complete and accurate transcripts of those documents with both textual and contextual annotation1

Diaryx en</summary>
    <content type="html"><![CDATA[<p>Diaryx is inspired by the Joseph Smith Papers Project, which is described on its website as:</p>
<blockquote>
<p>an effort to gather together all extant Joseph Smith documents and to publish complete and accurate transcripts of those documents with both textual and contextual annotation<a id="fnref1" href="#fn1" role="doc-noteref"><sup>1</sup></a></p>
</blockquote>
<p>Diaryx enables anyone to have their own “Papers Project.” It is designed to make archival, annotation, and publication accessible to anyone.</p>
<p>However, this description is incomplete: why is it important for a person to have their own Papers Project? In short, it is because a society undergoing significant social and technological shifts needs strong, new social infrastructure that caters to those who may be more prone to self-criticism, rejection-senstivity, and avoidance.</p>
<h2>The &quot;loneliness epidemic&quot;</h2>
<p>Around 20% of people consider themselves neurodivergent. Around 20% of people live with mental illness. Both of those numbers are increasing over time. War and strife fill the world, and debate and discourse grows more heated. It has never been more difficult to connect with people.</p>
<p>&quot;Alarming numbers of Americans are lonely. According to our recent national survey of approximately
950 Americans, 36% of respondents reported feeling lonely “frequently” or “almost all the time or all
the time” in the prior four weeks. A startling 61% of young people aged 18-25 and 51% of mothers
with young children reported these miserable degrees of loneliness.&quot;</p>
<p>The cost of disconnection is great. &quot;Loneliness is linked to early mortality and a wide array of serious
physical and emotional problems, including depression, anxiety, heart disease, substance abuse,
and domestic abuse.&quot;</p>
<p>Ultimately, as long as people respect each others' rights, there isn't any one specific way that a human ought to behave or function. As the world grows more connected, more people encounter other people who have differing cultures, behaviors, and sensitivities. These need to be met with greater kindness and understanding.</p>
<h2>Modern social technology fails to meet these needs</h2>
<p>Social media is a cesspool of misinformation and contention. &quot;When we asked respondents who or what they think contributes to loneliness in America,
technology (73%) topped the list&quot;. This result isn't surprising to anyone. But it is a shame that the technology designed to improve lives has instead darkened them with loneliness. We need to develop new social technology that respects the boundaries and honors the differences between people instead of blurring them.</p>
<h2>Diaryx honors differences</h2>
<p>[not finished]</p>
<section role="doc-endnotes">
<hr>
<ol>
<li id="fn1">
<p><a href="https://www.josephsmithpapers.org/articles/faq1#question-1">https://www.josephsmithpapers.org/articles/faq1#question-1</a><a href="#fnref1" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</section>
]]></content>
  </entry>
  <entry>
    <title>historica</title>
    <link href="https://main.diaryx.org/diaryx/historica/index.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/historica/index.html</id>
    <published>2026-09-03T23:04:43Z</published>
    <updated>2026-09-03T23:04:43Z</updated>
    <summary>diaryx.org / projects /
    
      historica
      
        Rust
        MIT / Apache-2.0
      
    
    
      Version control where the readable files are the authority.
    
  




historica is an experiment in readable, convergent version
control. It follows one non-</summary>
    <content type="html"><![CDATA[<section class="pj-head">
  <div class="wrap">
    <p><a class="crumb" href="https://main.diaryx.org/diaryx/about/#projects">diaryx.org / projects /</a></p>
    <div class="pj-title" style="margin-top: 1rem">
      <h1>historica</h1>
      <span class="pj-tags">
        <span class="tag-chip">Rust</span>
        <span class="tag-chip">MIT / Apache-2.0</span>
      </span>
    </div>
    <p class="pj-tagline">
      Version control where the readable files are the authority.
    </p>
  </div>
</section>
<section class="pj-main">
<div class="wrap pj-layout reveal">
<div class="pj-body">
<p>historica is an experiment in readable, convergent version
control. It follows one non-negotiable rule: a person must be able
to inspect the history, understand its relationships, and recover
stored content without decoding an opaque database or binary
operation log.</p>
<ul>
<li><strong>History as documents.</strong> Immutable revisions in a Merkle DAG, named by SHA-256 digests — the ID of a revision is what <code>shasum -a 256</code> already prints for its file.</li>
<li><strong>Honest rewrites.</strong> Supersession is explicit, so amending or rewriting a change is recorded rather than hidden.</li>
<li><strong>Convergence without coordination.</strong> History merges by set union; heads are discovered deterministically.</li>
<li><strong>A photograph is a photograph.</strong> Binary content is stored as payloads beside the documents — not as a diff with <code>+</code> down the margin.</li>
<li><strong>The corpus is the spec.</strong> Hand-written valid and invalid files are executed as tests, each refusal naming its reason.</li>
</ul>
<h2>Where it fits</h2>
<p>historica keeps a journal's history beside its entries —
convergent, inspectable, and durable on plain files — which is the
same bet everything else at Diaryx makes. In the app it does more
than remember: what you publish to a circle is a derived historica
store, and what your readers write back travels home the same way.</p>
<p>Two siblings extend it rather than living inside it:</p>
<ul>
<li><a href="https://github.com/diaryx-org/historica-remark">historica-remark</a> — a reader's remarks on a chain, and the layer that carries them back. The annotation model works with no historica at all.</li>
<li><a href="https://github.com/diaryx-org/historica-minisign">historica-minisign</a> — signing, so a remark that arrives under someone's name can be shown to be theirs.</li>
</ul>
<h2>Status</h2>
<p>The core model, strict revision and operation formats, and replay
all exist and are corpus-tested, and the app runs its publishing
and remark layers on them. It isn't a general-purpose VCS today.</p>
</div>
<aside class="pj-aside">
<div class="install">
<span class="install-head">Install</span>
<div class="cmd">cargo add historica <small>Rust</small></div>
</div>
<div class="facts">
<div class="row"><span class="k">Language</span><span class="v">Rust</span></div>
<div class="row"><span class="k">Used by</span><span class="v"><a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a> — entry history, publishing, and remark layers</span></div>
<div class="row"><span class="k">Source</span><span class="v"><a href="https://github.com/diaryx-org/historica">github.com/diaryx-org/historica</a></span></div>
<div class="row"><span class="k">Packages</span><span class="v"><a href="https://crates.io/crates/historica">crates.io/crates/historica</a></span></div>
<div class="row"><span class="k">License</span><span class="v">MIT or Apache-2.0</span></div>
</div>
</aside>
</div>
</section>
]]></content>
  </entry>
  <entry>
    <title>fig</title>
    <link href="https://main.diaryx.org/diaryx/fig/index.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/fig/index.html</id>
    <published>2026-08-23T01:23:55Z</published>
    <updated>2026-08-23T01:23:55Z</updated>
    <summary>diaryx.org / projects /
    
      fig
      
        Zig
        MIT / Apache-2.0
      
    
    
      Lossless parsing and editing of config files — down to every
      comment, key order, and blank line.
    
  




Editing config files programmatically shouldn&apos;t m</summary>
    <content type="html"><![CDATA[<section class="pj-head">
  <div class="wrap">
    <p><a class="crumb" href="https://main.diaryx.org/diaryx/about/#projects">diaryx.org / projects /</a></p>
    <div class="pj-title" style="margin-top: 1rem">
      <h1>fig</h1>
      <span class="pj-tags">
        <span class="tag-chip">Zig</span>
        <span class="tag-chip">MIT / Apache-2.0</span>
      </span>
    </div>
    <p class="pj-tagline">
      Lossless parsing and editing of config files — down to every
      comment, key order, and blank line.
    </p>
  </div>
</section>
<section class="pj-main">
<div class="wrap pj-layout reveal">
<div class="pj-body">
<p>Editing config files programmatically shouldn't mean reformatting
them. fig parses JSON, JSON5, YAML, TOML, ZON, and its own dialect
into a lossless AST, then splices your change in: a one-line diff,
everything else byte-for-byte identical.</p>
<ul>
<li><strong>Set a value, keep the file.</strong> <code>fig set config.yaml service.replicas 5</code> touches one line.</li>
<li><strong>Comments are data.</strong> Attach one inline: <code>fig comment --inline config.yaml service.replicas &quot;bumped&quot;</code> — and they survive every edit and conversion.</li>
<li><strong>Convert without loss.</strong> YAML → JSON5 → TOML carries comments along.</li>
<li><strong>Edit embedded config too.</strong> Frontmatter inside Markdown is just another document to fig.</li>
</ul>
<h2>Where it fits</h2>
<p>fig is the metadata layer of <a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a> —
frontmatter in every entry goes through it, and
<a href="https://main.diaryx.org/diaryx/flower/index.html">flower</a> is a structural editor built on
its tree. Standalone, it's a library (crates.io, npm) and a CLI
for anyone who scripts against config files.</p>
<h2>Status</h2>
<p>Actively maintained and published: the Rust crate wraps the Zig
core, an npm package ships it for JavaScript, and Homebrew carries
the CLI.</p>
</div>
<aside class="pj-aside">
<div class="install">
<span class="install-head">Install</span>
<div class="cmd">brew install diaryx-org/tap/fig <small>CLI</small></div>
<div class="cmd">cargo add fig <small>Rust</small></div>
<div class="cmd">npm install @diaryx/fig <small>JavaScript</small></div>
</div>
<div class="facts">
<div class="row"><span class="k">Language</span><span class="v">Zig (Rust bindings)</span></div>
<div class="row"><span class="k">Used by</span><span class="v"><a href="https://main.diaryx.org/diaryx/prov/index.html">prov</a> · <a href="https://main.diaryx.org/diaryx/flower/index.html">flower</a> · <a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a></span></div>
<div class="row"><span class="k">Source</span><span class="v"><a href="https://github.com/diaryx-org/fig">github.com/diaryx-org/fig</a></span></div>
<div class="row"><span class="k">Packages</span><span class="v"><a href="https://crates.io/crates/fig">crates.io/crates/fig</a> · <a href="https://www.npmjs.com/package/@diaryx/fig">npmjs.com/@diaryx/fig</a></span></div>
<div class="row"><span class="k">License</span><span class="v">MIT or Apache-2.0</span></div>
</div>
</aside>
</div>
</section>
]]></content>
  </entry>
  <entry>
    <title>flower</title>
    <link href="https://main.diaryx.org/diaryx/flower/index.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/flower/index.html</id>
    <published>2026-08-23T01:23:55Z</published>
    <updated>2026-08-23T01:23:55Z</updated>
    <summary>diaryx.org / projects /
    
      flower
      
        Rust
        MIT / Apache-2.0
      
    
    
      A structural editor for config files — it edits the tree, not the
      characters.
    
  




Where a text editor edits characters, flower edits the tree. You</summary>
    <content type="html"><![CDATA[<section class="pj-head">
  <div class="wrap">
    <p><a class="crumb" href="https://main.diaryx.org/diaryx/about/#projects">diaryx.org / projects /</a></p>
    <div class="pj-title" style="margin-top: 1rem">
      <h1>flower</h1>
      <span class="pj-tags">
        <span class="tag-chip">Rust</span>
        <span class="tag-chip">MIT / Apache-2.0</span>
      </span>
    </div>
    <p class="pj-tagline">
      A structural editor for config files — it edits the tree, not the
      characters.
    </p>
  </div>
</section>
<section class="pj-main">
<div class="wrap pj-layout reveal">
<div class="pj-body">
<p>Where a text editor edits characters, flower edits the tree. You
navigate the parsed config structurally — into mappings, along
sequences, down to scalars — and edit one value at a time. Every
change is a path-addressed, lossless splice through fig's editor:
the bytes you didn't touch stay byte-for-byte identical, and the
document is only ever committed in a valid state.</p>
<ul>
<li><strong>Two views of the same tree.</strong> An indented, type-colored tree; or a settings-menu page view that sinks the fields nobody types below the ones they do.</li>
<li><strong>Typed scalar edits.</strong> Booleans, numbers, nulls, and text are committed through fig's validated replace — not typed freehand.</li>
<li><strong>Everything fig reads.</strong> JSON/JSONC/JSON5, YAML, TOML, ZON, and the fig dialect.</li>
</ul>
<h2>Where it fits</h2>
<p>flower is the config sibling of <a href="https://main.diaryx.org/diaryx/leaf/index.html">leaf</a>:
leaf's caret model is right for permissive document formats; a
strict config grammar wants a structural one. It edits through
<a href="https://main.diaryx.org/diaryx/fig/index.html">fig</a>'s tree, and in
<a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a> it's a natural front end for vault
configuration and frontmatter.</p>
<h2>Status</h2>
<p>Early prototype. Navigation, both views, typed edits, deletes, and
save all work today; the roadmap in the repo says what isn't here
yet.</p>
</div>
<aside class="pj-aside">
<div class="install">
<span class="install-head">Install</span>
<div class="cmd">cargo add flower-core <small>Rust</small></div>
</div>
<div class="facts">
<div class="row"><span class="k">Language</span><span class="v">Rust (on fig)</span></div>
<div class="row"><span class="k">Built on</span><span class="v"><a href="https://main.diaryx.org/diaryx/fig/index.html">fig</a></span></div>
<div class="row"><span class="k">Used by</span><span class="v"><a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a> — config &amp; metadata editing</span></div>
<div class="row"><span class="k">Source</span><span class="v"><a href="https://github.com/diaryx-org/flower">github.com/diaryx-org/flower</a></span></div>
<div class="row"><span class="k">Packages</span><span class="v"><a href="https://crates.io/crates/flower-core">crates.io/crates/flower-core</a></span></div>
<div class="row"><span class="k">License</span><span class="v">MIT or Apache-2.0</span></div>
</div>
</aside>
</div>
</section>
]]></content>
  </entry>
  <entry>
    <title>leaf</title>
    <link href="https://main.diaryx.org/diaryx/leaf/index.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/leaf/index.html</id>
    <published>2026-08-23T01:23:55Z</published>
    <updated>2026-08-23T01:23:55Z</updated>
    <summary>diaryx.org / projects /
    
      leaf
      
        Rust · Swift
        MIT / Apache-2.0
      
    
    
      A caret-based rich-text editor that edits the document&apos;s AST.
    
  




leaf gives you an ordinary text caret — mouse, selection, a
formatting toolbar</summary>
    <content type="html"><![CDATA[<section class="pj-head">
  <div class="wrap">
    <p><a class="crumb" href="https://main.diaryx.org/diaryx/about/#projects">diaryx.org / projects /</a></p>
    <div class="pj-title" style="margin-top: 1rem">
      <h1>leaf</h1>
      <span class="pj-tags">
        <span class="tag-chip">Rust · Swift</span>
        <span class="tag-chip">MIT / Apache-2.0</span>
      </span>
    </div>
    <p class="pj-tagline">
      A caret-based rich-text editor that edits the document's AST.
    </p>
  </div>
</section>
<section class="pj-main">
<div class="wrap pj-layout reveal">
<div class="pj-body">
<p>leaf gives you an ordinary text caret — mouse, selection, a
formatting toolbar — and turns every keystroke into an
offset-addressed edit on twig's tree. The document stays a live,
round-trippable AST the whole time you type into it, so a Markdown
file and a Djot file are edited through exactly the same
operations.</p>
<ul>
<li><strong>Two views, one rendering path.</strong> Source (caret in raw bytes) and WYSIWYG (<code>**bold**</code> painted bold, delimiters hidden) — every rendered glyph maps back to its source byte, so carets and clicks ride the visible text in either.</li>
<li><strong>One core, many frontends.</strong> A frontend-neutral core; embeddable widgets for ratatui, gpui, AppKit/UIKit (via UniFFI), and the browser (via wasm).</li>
<li><strong>Thin hosts everywhere.</strong> A terminal editor, a GUI app, an iOS host, and a web demo are all thin wrappers around the same widget.</li>
</ul>
<h2>Where it fits</h2>
<p>leaf is the editor underneath <a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a>'s writing
surface — the same core that renders an entry on Mac renders it on
iPhone. It edits documents through <a href="https://main.diaryx.org/diaryx/twig/index.html">twig</a>'s
tree. Standalone, it's embeddable anywhere a rich-text view over
plain files belongs.</p>
<h2>Status</h2>
<p>Work in progress, and open about it: caret editing, mouse,
selection, and both views work today; soft-wrap edge cases, inline
images, and undo/redo are the known next steps.</p>
</div>
<aside class="pj-aside">
<div class="install">
<span class="install-head">Install</span>
<div class="cmd">cargo add leaf-core <small>Rust</small></div>
</div>
<div class="facts">
<div class="row"><span class="k">Language</span><span class="v">Rust · Swift · TypeScript (web package)</span></div>
<div class="row"><span class="k">Built on</span><span class="v"><a href="https://main.diaryx.org/diaryx/twig/index.html">twig</a></span></div>
<div class="row"><span class="k">Used by</span><span class="v"><a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a> — the writing surface</span></div>
<div class="row"><span class="k">Source</span><span class="v"><a href="https://github.com/diaryx-org/leaf">github.com/diaryx-org/leaf</a></span></div>
<div class="row"><span class="k">Packages</span><span class="v"><a href="https://crates.io/crates/leaf-core">crates.io/crates/leaf-core</a></span></div>
<div class="row"><span class="k">License</span><span class="v">MIT or Apache-2.0</span></div>
</div>
</aside>
</div>
</section>
]]></content>
  </entry>
  <entry>
    <title>prov</title>
    <link href="https://main.diaryx.org/diaryx/prov/index.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/prov/index.html</id>
    <published>2026-08-23T01:23:55Z</published>
    <updated>2026-08-23T01:23:55Z</updated>
    <summary>diaryx.org / projects /
    
      prov
      
        Rust
        MIT / Apache-2.0
      
    
    
      Plaintext Records, Organized and Verifiable — a self-describing
      workspace of plain documents.
    
  




A prov workspace is a set of documents whose struc</summary>
    <content type="html"><![CDATA[<section class="pj-head">
  <div class="wrap">
    <p><a class="crumb" href="https://main.diaryx.org/diaryx/about/#projects">diaryx.org / projects /</a></p>
    <div class="pj-title" style="margin-top: 1rem">
      <h1>prov</h1>
      <span class="pj-tags">
        <span class="tag-chip">Rust</span>
        <span class="tag-chip">MIT / Apache-2.0</span>
      </span>
    </div>
    <p class="pj-tagline">
      Plaintext Records, Organized and Verifiable — a self-describing
      workspace of plain documents.
    </p>
  </div>
</section>
<section class="pj-main">
<div class="wrap pj-layout reveal">
<div class="pj-body">
<p>A prov workspace is a set of documents whose structure lives in the
documents' own embedded metadata (frontmatter) — not in the
filesystem layout, and not in an app-private sidecar folder. The
files describe themselves, so anything that can read text can read
the whole organization.</p>
<ul>
<li><strong>Documents.</strong> Plain Markdown with YAML frontmatter; no database, no proprietary container.</li>
<li><strong>Relations.</strong> An index lists what belongs to it; each child names its parent. Both halves written down, in the files.</li>
<li><strong>Identity.</strong> Permanent opaque identifiers minted into the record itself, stable across renames, moves, and republication.</li>
<li><strong>Fixity.</strong> Content hashes that make silent drift detectable instead of assumed absent.</li>
<li><strong>A thin CLI.</strong> The <code>prov</code> binary for working with workspaces without any app at all.</li>
</ul>
<h2>Where it fits</h2>
<p>prov is the vault engine underneath <a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a> — the
part that makes a folder of Markdown behave like an archive. It
stands on <a href="https://main.diaryx.org/diaryx/fig/index.html">fig</a> for the frontmatter and
<a href="https://main.diaryx.org/diaryx/twig/index.html">twig</a> for the documents. Standalone, it's a
Rust library anyone can build on.</p>
<h2>Status</h2>
<p>Works for simple workspaces; active development is incorporating
it into Diaryx. Released to crates.io as eleven crates via one
tagged commit.</p>
</div>
<aside class="pj-aside">
<div class="install">
<span class="install-head">Install</span>
<div class="cmd">brew install diaryx-org/tap/prov <small>CLI</small></div>
<div class="cmd">cargo install prov-cli <small>CLI</small></div>
<div class="cmd">cargo add prov <small>library</small></div>
</div>
<div class="facts">
<div class="row"><span class="k">Language</span><span class="v">Rust</span></div>
<div class="row"><span class="k">Built on</span><span class="v"><a href="https://main.diaryx.org/diaryx/fig/index.html">fig</a> · <a href="https://main.diaryx.org/diaryx/twig/index.html">twig</a> · <a href="https://github.com/diaryx-org/moid">moid</a></span></div>
<div class="row"><span class="k">Used by</span><span class="v"><a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a> — the vault engine</span></div>
<div class="row"><span class="k">Source</span><span class="v"><a href="https://github.com/diaryx-org/prov">github.com/diaryx-org/prov</a></span></div>
<div class="row"><span class="k">Packages</span><span class="v"><a href="https://crates.io/crates/prov">crates.io/crates/prov</a> · <a href="https://docs.rs/prov">docs.rs/prov</a></span></div>
<div class="row"><span class="k">License</span><span class="v">MIT or Apache-2.0</span></div>
</div>
</aside>
</div>
</section>
]]></content>
  </entry>
  <entry>
    <title>twig</title>
    <link href="https://main.diaryx.org/diaryx/twig/index.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/twig/index.html</id>
    <published>2026-08-23T01:23:55Z</published>
    <updated>2026-08-23T01:23:55Z</updated>
    <summary>diaryx.org / projects /
    
      twig
      
        Zig
        MIT / Apache-2.0
      
    
    
      A round-trippable document AST for Markdown, Djot, and HTML.
    
  




Where fig parses configuration files, twig parses
documents. It&apos;s comparable to Pandoc, but</summary>
    <content type="html"><![CDATA[<section class="pj-head">
  <div class="wrap">
    <p><a class="crumb" href="https://main.diaryx.org/diaryx/about/#projects">diaryx.org / projects /</a></p>
    <div class="pj-title" style="margin-top: 1rem">
      <h1>twig</h1>
      <span class="pj-tags">
        <span class="tag-chip">Zig</span>
        <span class="tag-chip">MIT / Apache-2.0</span>
      </span>
    </div>
    <p class="pj-tagline">
      A round-trippable document AST for Markdown, Djot, and HTML.
    </p>
  </div>
</section>
<section class="pj-main">
<div class="wrap pj-layout reveal">
<div class="pj-body">
<p>Where fig parses configuration files, twig parses
<em>documents</em>. It's comparable to Pandoc, but with different
goals: not conversion for its own sake, but exposing the abstract
syntax tree so precise operations can be performed on it — then
writing the document back, faithfully.</p>
<ul>
<li><strong>Round-trippable by intent.</strong> First-class support is for formats you can edit and re-serialize without loss — not presentation formats like PDF.</li>
<li><strong>Markdown.</strong> Fully CommonMark 0.31.2 conformant: 652/652 spec examples passing.</li>
<li><strong>Djot.</strong> 100% conformant with the djot.js corpus — every case that defines an HTML expectation passes.</li>
<li><strong>HTML.</strong> A generic-markup parser and serializer with forgiving, document-oriented tree construction.</li>
<li><strong>An editor surface.</strong> Offset-addressed edits, ancestor queries, inline toggles — the operations a text editor needs, defined on the tree.</li>
</ul>
<h2>Where it fits</h2>
<p>twig is the document model everything at Diaryx is written
against — every entry in a vault is a twig document, and
<a href="https://main.diaryx.org/diaryx/leaf/index.html">leaf</a> is a rich-text editor over its tree.
Standalone, it's a library (crates.io as <code>twig-doc</code>)
for anyone who needs to treat markup as data.</p>
</div>
<aside class="pj-aside">
<div class="install">
<span class="install-head">Install</span>
<div class="cmd">brew install diaryx-org/tap/twig <small>CLI</small></div>
<div class="cmd">cargo add twig-doc <small>Rust</small></div>
</div>
<div class="facts">
<div class="row"><span class="k">Language</span><span class="v">Zig (Rust bindings)</span></div>
<div class="row"><span class="k">Used by</span><span class="v"><a href="https://main.diaryx.org/diaryx/prov/index.html">prov</a> · <a href="https://main.diaryx.org/diaryx/leaf/index.html">leaf</a> · <a href="https://main.diaryx.org/diaryx/index.html">Diaryx</a></span></div>
<div class="row"><span class="k">Source</span><span class="v"><a href="https://github.com/diaryx-org/twig">github.com/diaryx-org/twig</a></span></div>
<div class="row"><span class="k">Packages</span><span class="v"><a href="https://crates.io/crates/twig-doc">crates.io/crates/twig-doc</a> · <a href="https://docs.rs/twig-doc">docs.rs/twig-doc</a></span></div>
<div class="row"><span class="k">License</span><span class="v">MIT or Apache-2.0</span></div>
</div>
</aside>
</div>
</section>
]]></content>
  </entry>
  <entry>
    <title>LICENSE</title>
    <link href="https://main.diaryx.org/diaryx/docs/LICENSE.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/docs/LICENSE.html</id>
    <published>2026-08-09T01:26:47Z</published>
    <updated>2026-08-09T01:26:47Z</updated>
    <summary>Diaryx is proprietary software. All rights are
reserved by the copyright holder. For licensing inquiries or exceptions, contact
contact@diaryx.org.

Diaryx Proprietary License
Copyright © 2025–2026 Adam Harris. All rights reserved.
1. Ownership
The Diaryx software, source code</summary>
    <content type="html"><![CDATA[<p>Diaryx is proprietary software. All rights are
reserved by the copyright holder. For licensing inquiries or exceptions, contact
<a href="mailto:contact@diaryx.org">contact@diaryx.org</a>.</p>
<hr />
<h1>Diaryx Proprietary License</h1>
<p><strong>Copyright © 2025–2026 Adam Harris. All rights reserved.</strong></p>
<h2>1. Ownership</h2>
<p>The Diaryx software, source code, documentation, and all associated materials in
this repository (the &quot;Software&quot;) are the exclusive property of Adam Harris (the
&quot;Licensor&quot;) and are protected by copyright and other intellectual property laws.</p>
<h2>2. Source-Available, Not Open Source</h2>
<p>The Licensor publishes the source code of the Software so that it may be read,
audited, and referenced. Making the source publicly viewable does <strong>not</strong> grant
any license to use, copy, modify, merge, publish, distribute, sublicense, sell,
or create derivative works from the Software, in whole or in part, except as
expressly permitted in a separate written agreement signed by the Licensor.</p>
<h2>3. Reservation of Rights</h2>
<p>All rights not expressly granted are reserved by the Licensor. No rights are
granted by implication, estoppel, or otherwise. Nothing in this license shall be
construed as a waiver of any of the Licensor's rights.</p>
<h2>4. Permitted Use</h2>
<p>You may use the Diaryx application only through the official channels the
Licensor provides (for example, <a href="https://app.diaryx.org">app.diaryx.org</a> and
official app-store distributions), subject to the applicable
<a href="https://main.diaryx.org/diaryx/terms.html">Terms of Service</a> and <a href="https://main.diaryx.org/diaryx/privacy.html">Privacy Policy</a>. This license
does not grant any right to run, host, or redistribute the Software yourself.</p>
<h2>5. Contributions</h2>
<p>Unless a separate written agreement states otherwise, any contribution you submit
to this repository is provided under, and you assign to the Licensor all right,
title, and interest in, such contribution, so that the Licensor may license the
combined work under these proprietary terms. See
<span class="unpublished-link" title="This page isn’t published">Contributing to Diaryx</span>.</p>
<h2>6. Third-Party Components</h2>
<p>The Software may include or depend on third-party components that are licensed
under their own terms. Those components remain governed by their respective
licenses. This license applies only to the original work of the Licensor.</p>
<h2>7. No Warranty</h2>
<p><strong>As far as the law allows, the Software is provided &quot;as is&quot;, without warranty or
condition of any kind, and the Licensor will not be liable for any damages
arising out of these terms or the use or nature of the Software, under any kind
of legal claim.</strong></p>
<h2>8. Termination</h2>
<p>Any use of the Software not expressly authorized by this license or a separate
written agreement is a violation of the Licensor's rights and automatically
terminates any permissions you may otherwise have.</p>
<hr />
<p><em>For prior public releases: versions of this Software distributed under a
previous license remain governed by the terms under which they were received.
This license governs the current and future versions of the Software.</em></p>
]]></content>
  </entry>
  <entry>
    <title>Support</title>
    <link href="https://main.diaryx.org/diaryx/support.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/support.html</id>
    <published>2026-07-30T00:00:00Z</published>
    <updated>2026-07-30T16:36:40Z</updated>
    <summary>Thank you for using Diaryx! If you need support, please contact us at contact@diaryx.org.
You can also email the founder directly at adam@diaryx.org. He is very friendly!</summary>
    <content type="html"><![CDATA[<p>Thank you for using Diaryx! If you need support, please contact us at <a href="mailto:contact@diaryx.org">contact@diaryx.org</a>.</p>
<p>You can also email the founder directly at <a href="mailto:adam@diaryx.org">adam@diaryx.org</a>. He is very friendly!</p>
]]></content>
  </entry>
  <entry>
    <title>Document Record Spec</title>
    <link href="https://main.diaryx.org/diaryx/docs/Document Record Spec.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/docs/Document Record Spec.html</id>
    <published>2026-07-03T17:50:09-07:00</published>
    <updated>2026-08-17T01:45:46Z</updated>
    <summary>Status: draft
A document record is the archival unit of a Diaryx workspace: everything the workspace knows about one gathered document. It is the target shape that every importer emits, the structure that annotation lives in, and the referent that identifiers point at.
The design</summary>
    <content type="html"><![CDATA[<p><strong>Status: draft</strong></p>
<p>A <em>document record</em> is the archival unit of a Diaryx workspace: everything the workspace knows about one gathered document. It is the target shape that every importer emits, the structure that annotation lives in, and the referent that identifiers point at.</p>
<p>The design follows the <a href="https://main.diaryx.org/diaryx/docs/PHILOSOPHY.html">PHILOSOPHY</a>: gather, transcribe, annotate, publish — the same structure the Joseph Smith Papers Project uses for each document (artifact, transcript layers, source note, editorial annotation). Everything is plain text — Markdown with frontmatter for prose, YAML for the card that stands in for a file that is not prose — and a document record is fully legible in any text editor.</p>
<h2>Components</h2>
<p>A document record consists of:</p>
<ol>
<li><strong>Artifact</strong> — the original file, byte-for-byte (a scan, photo, PDF, audio file, or born-digital original). Never modified.</li>
<li><strong>Attachment sidecar</strong> (the <em>catalog card</em>) — prov's <code>&lt;payload&gt;.&lt;ext&gt;.yaml</code>, minted beside the artifact by <code>attach</code>. It carries the artifact's title, its <code>content:</code> pointer, typed links, and provenance metadata. This <em>is</em> the record: there is exactly one document per artifact, and it is the sidecar.</li>
<li><strong>Transcription(s)</strong> — zero or more Markdown files containing the artifact's textual content. Each is a document in its own right: independently editable, publishable, audience-filterable, and addressable.</li>
<li><strong>Annotation</strong> — footnotes within a transcription, plus sibling note files for document-level commentary, linked from the catalog card.</li>
</ol>
<p>Only the artifact and its sidecar are required. A born-digital Markdown import needs no transcription; a photo of a letter usually wants one.</p>
<h3>One document per artifact</h3>
<p>An earlier draft of this spec gave the artifact a Markdown catalog card of its own. That card was a <em>second</em> document about the same file, since <code>attach</code> had already minted the sidecar — two nodes in the tree, two rows in a lens, and no answer to which of them the record is. A transcription link would have had two places to hang off.</p>
<p>So the card is the sidecar, and there is no Markdown card. The cost is real and is accepted: a whole-file YAML document has no prose body, so the free-form <em>source note</em> is a frontmatter string (<code>source_note:</code>) rather than paragraphs under a fence. Anything longer than a note belongs in a sibling commentary file (see <strong>Annotation</strong>), which is where document-level prose was always meant to live.</p>
<h2>Storage layout</h2>
<p>An artifact and its sidecar are <strong>siblings in an <code>attachments/</code> directory beside the index that contains them</strong> — the placement <code>import_attachment</code> writes and prov's reverse index requires (<code>photo.jpg</code> ⇄ <code>photo.jpg.yaml</code> is found by name alone, so the pair cannot be split). The containing index is resolved by the same rules a story written that day would use, so an artifact is filed under the period index the vault already files writing into, rather than into a folder of its own:</p>
<pre><code>Daily/2026/
  index.md                              (the containing index; contents: links the sidecar by id)
  attachments/
    letter-from-may-1943.eml            (artifact, byte-for-byte)
    letter-from-may-1943.eml.yaml       (catalog card: content:, attachment: true, transcription:, provenance)
    letter-from-may-1943.transcript.md  (transcription)
</code></pre>
<p>There is no record folder and no date prefix. A record is a <em>link neighbourhood</em>, not a directory: the sidecar names its payload through <code>content:</code>, its transcriptions through <code>transcription:</code>, and its container through the index's spanning field. Tools must follow those links rather than assume any path — including <code>attachments/</code>, which is where writes land, not a location anything may rely on when reading.</p>
<p>Records are not confined to <code>Documents/</code>. That directory was this spec's earlier convention; placement now follows the vault's declared date view, and a user may move a record anywhere.</p>
<p>Born-digital text imports (a Day One journal, a folder of Markdown) have no artifact, and so no card and no <code>attachments/</code> directory: they import as plain entries, filed into the same date structure by the same placement rules. A record is what an artifact gets; an entry is what text that was never anything else gets.</p>
<h2>The attachment sidecar (catalog card)</h2>
<p>Extends prov's sidecar — which <code>attach</code> mints carrying <code>title</code>, <code>content:</code> and <code>attachment: true</code> — with transcription links and provenance metadata. The whole file is the metadata; there are no fences:</p>
<pre><code class="language-yaml">title: Letter from Ruth Harris, May 1943
content: letter-1943.jpg
attachment: true
created: 2026-08-16
transcription:
- '[Letter from Ruth Harris, May 1943 (transcript)](letter-1943.transcript.md)'
source: Grandma's shoebox, box 2
source_note: &gt;-
  Water-stained but legible. Ruth describes the week Dad was born.
  This is the only surviving letter from this period.
date_of_document: 1943-05-12
people:
- Ruth Harris
places:
- Ogden, Utah
</code></pre>
<p>Two keys are prov's and are not this spec's to redefine: <code>content:</code> is the pointer to the payload, resolved relative to the sidecar's own folder, and <code>attachment: true</code> is what stops prov reading the payload as prose. Containment is not a key here at all — the <em>index</em> gains the spanning link, in id-form, so the relationship survives the sidecar being moved.</p>
<p>The two dates answer different questions and must not be conflated. <code>created</code> is <strong>when Diaryx/prov made the document</strong> — an act of the software, stamped like any other document's. <code>date_of_document</code> is <strong>when the original was made</strong>, which is a fact about the world that often only its owner knows. A scan made today of a letter from 1943 has <code>created: 2026-08-16</code> and <code>date_of_document: 1943-05-12</code>.</p>
<p>This matters most to importers, which are the tempting place to blur it: an EXIF origin date, an email <code>Date:</code> header, and a Day One entry's timestamp are all statements about the original, so they belong in <code>date_of_document</code>. <code>created</code> is never inferred from the source — it is when the record entered this archive, and nothing else.</p>
<h3>Frontmatter keys</h3>
<table>
<thead>
<tr>
<th>Key</th>
<th>Type</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>content</code></td>
<td>path</td>
<td>The artifact this card represents, relative to the card (prov's, not this spec's)</td>
</tr>
<tr>
<td><code>attachment</code></td>
<td>bool</td>
<td><code>true</code> — marks the card a sidecar rather than prose (prov's)</td>
</tr>
<tr>
<td><code>transcription</code></td>
<td>link list</td>
<td>Transcription files for this artifact</td>
</tr>
<tr>
<td><code>source_note</code></td>
<td>string</td>
<td>Free-form note: condition, context, why it matters. The body a whole-file card cannot have</td>
</tr>
<tr>
<td><code>source</code></td>
<td>string</td>
<td>Provenance: where the artifact came from (see <strong>Provenance</strong> below)</td>
</tr>
<tr>
<td><code>date_of_document</code></td>
<td>date, or <code>unknown</code></td>
<td>When the original was made (distinct from <code>created</code>, which is when Diaryx made the document). See below</td>
</tr>
<tr>
<td><code>people</code>, <code>places</code></td>
<td>string lists</td>
<td>Entities appearing in or associated with the document</td>
</tr>
</tbody>
</table>
<p>All provenance keys are optional. Unknown keys remain permitted, as everywhere in Diaryx frontmatter.</p>
<h3><code>date_of_document: unknown</code></h3>
<p>A date lens groups by a <strong>chain</strong> — <code>[date_of_document, created, updated]</code>, declared per-vault as a view's <code>group:</code> — and the chain is <em>first key present wins</em>, not first key parseable. A grain then cuts the winning value, and validates rather than slices: <code>banana</code> at year grain is not the group <code>bana</code>, it is no group at all.</p>
<p>Those two rules compose into the marker. Writing</p>
<pre><code class="language-yaml">date_of_document: unknown
</code></pre>
<p>stops the chain at the first link and yields a value no grain can cut, so the document files as <strong>undated</strong> instead of inheriting the day it was scanned. Verified against prov: a document carrying <code>date_of_document: unknown</code> alongside <code>created: 2026-01-01</code> lands in <code>(ungrouped)</code>, while the same document without the marker lands in <code>2026</code>.</p>
<p>This is what a shoebox needs. A folder of 200 undated scans imported on one afternoon would otherwise all inherit that afternoon through <code>created</code>, burying a year of the reader's real archive under a day that means nothing about any of the documents. Undated is the honest answer, and the marker is how a record gives it.</p>
<p>Two consequences worth stating plainly:</p>
<ul>
<li><strong>The marker is a convention, not a mechanism.</strong> Nothing privileges the literal string <code>unknown</code> — any uncuttable value stops the chain identically, so a typo'd <code>May 1943</code> silently files as undated too. <code>unknown</code> earns its place by saying <em>deliberately</em> unknown to the next human, not by doing anything special to the engine. (Nor does anything catch the typo: prov's <code>check</code> does not validate <code>type: date</code> values, which is a real gap and not this spec's to close.)</li>
<li><strong><code>date_of_document</code> is already load-bearing for placement.</strong> Period indexes are resolved by the date they carry rather than by title — real ones are titled <code>2025-03 index</code>, <code>December 2025</code>, <code>March 2026</code> and <code>07</code>, and no title rule matches all four — so the index-creating path stamps <code>date_of_document</code> on each index it makes. The key is structural, not merely descriptive, and a tool writing it is participating in filing.</li>
</ul>
<h2>Transcription files</h2>
<p>A transcription is an ordinary Markdown file — fenced frontmatter and a prose body, unlike the card — with a back-link to that card:</p>
<pre><code class="language-yaml">---
title: Letter from Ruth Harris, May 1943 (transcript)
transcription_of: '[Letter from Ruth Harris, May 1943](letter-1943.jpg.yaml)'
transcription_status: needs_review
audience:
- family
---
Dear Mother,

We are all well here, though the rain has not let up since Tuesday...[^1]

[^1]: Spring 1943 was unusually wet in northern Utah.
</code></pre>
<h3>Keys</h3>
<table>
<thead>
<tr>
<th>Key</th>
<th>Type</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>transcription_of</code></td>
<td>link</td>
<td>Back-link to the attachment sidecar (pairs with <code>transcription</code>, following the <code>link</code>/<code>link_of</code> convention). It names the <em>card</em>, not the payload — the card is the record, and a payload prov cannot read as text has nothing to link back from</td>
</tr>
<tr>
<td><code>transcription_status</code></td>
<td>enum</td>
<td><code>draft</code> → <code>needs_review</code> → <code>verified</code></td>
</tr>
</tbody>
</table>
<h3>Status lifecycle</h3>
<p>Machine-produced text (OCR, speech-to-text) is a <em>draft pending human review</em>, never silently treated as truth:</p>
<ul>
<li><code>draft</code> — machine-generated or in-progress, not yet human-reviewed</li>
<li><code>needs_review</code> — complete but awaiting verification against the artifact</li>
<li><code>verified</code> — a human has checked it against the artifact</li>
</ul>
<p>This gives users the archivist workflow: gather → transcribe → verify → annotate → publish. <code>verified</code> is a <em>position in that workflow</em>, not an attributed claim about particular bytes — see <strong>Provenance</strong> below for what it does not yet say, and what prov will eventually let it say.</p>
<h3>Multiple transcription layers</h3>
<p><code>transcription</code> is a list. A record may carry multiple layers — e.g. a <em>verbatim</em> transcript (original spelling, strikethroughs preserved) and a <em>normalized</em> reading copy — as separate files. No layer-type key is defined yet; distinguish layers by title until real usage motivates one.</p>
<h2>Annotation</h2>
<p>Two forms, both plain Markdown:</p>
<ol>
<li><strong>In-text annotation</strong>: standard Markdown footnotes inside the transcription file.</li>
<li><strong>Document-level commentary</strong>: sibling Markdown files linked from the catalog card (via <code>links</code> or <code>contents</code>), for essays, research notes, or historical introductions about the document.</li>
</ol>
<p><strong>Explicitly out of scope: standoff annotation.</strong> No character-offset or range anchors into transcripts — offsets break on every edit. If in-text anchoring beyond footnotes is ever needed, anchor to quoted text snippets (fuzzy-matched), not positions.</p>
<h2>Provenance</h2>
<p>This spec's <code>source</code> key and <code>transcription_status</code> lifecycle predate prov's <a href="https://github.com/diaryx-org/prov/blob/main/docs/proposals/provenance/proposal-provenance-v1.md">provenance proposal</a>, which reaches for the same goals with more mechanism behind it. That proposal is an <strong>early draft</strong> — eight open questions, three of which change the shape of the rest, and a Phase 0 that is <em>carry only</em> — so nothing here changes today. What this section fixes is the layering, so that neither side grows a duplicate of the other.</p>
<h3><code>transcription_status</code> is not prov's <code>verified</code>, and should not become it</h3>
<p>prov proposes <code>verified: [{by, at, of}]</code> — an append-only list of dated, attributed confirmations, each bound to the fixity digest it was made against — with trust tiers <em>derived</em> from the entries rather than stored. Diaryx's <code>transcription_status</code> looks like a smaller version of that, but the two answer different questions and both are worth keeping:</p>
<ul>
<li><code>transcription_status</code> is a <strong>position in the transcription workflow</strong>. <code>needs_review</code> has no prov equivalent and will not get one: prov's proposal lists workflow as a non-goal (&quot;no review queues, no assignment, no approval states&quot;).</li>
<li><code>verified</code> is an <strong>attributed, dated, digest-bound claim</strong>. It says who checked, when, and against which bytes.</li>
</ul>
<p>The intended relationship is that the second <em>backs</em> the first, rather than replacing it: <code>transcription_status: verified</code> is legitimate only when a <code>verified</code> entry exists whose <code>of</code> matches the transcription's current digest.</p>
<h3>The gap this leaves open today</h3>
<p>Diaryx's <code>verified</code> is a bare enum, so it survives an edit to the transcription it describes. Someone checks a transcript against the artifact, someone else fixes a line, and the frontmatter still claims the transcript is verified — prov's proposal names this exact failure and calls it worse than having no vocabulary at all, &quot;because it launders staleness as assurance.&quot;</p>
<p>Diaryx stamps fixity over attachments by default, and a vault can widen it to <code>fixity: all</code> in <code>config.yaml</code>, which is what puts a <code>content_hash</code> on a transcript's own body — so the ingredient is available, but a vault that wants checkable transcription claims has to ask for it. When prov's Phase 2 lands, the demotion rule comes with it: a transcript whose bytes no longer match the digest its verification was made against falls back to <code>needs_review</code>, and prov reports a <code>VerificationStale</code> finding. Until then this is a known, unenforced gap, not a solved problem — and <code>transcription_status: verified</code> should be read as &quot;a human said so at some point,&quot; not as a checkable claim.</p>
<p>Two rules from the proposal apply to Diaryx as written, and are worth stating here because importers are the tempting place to break them:</p>
<ul>
<li><strong>Nothing auto-promotes a transcription to <code>verified</code>.</strong> A clean OCR run, a confident speech-to-text score, and a passing <code>prov check</code> are all attestations about <em>state</em>; verification is a claim about <em>meaning</em>, and only a person or a named process makes one.</li>
<li><strong>A stored verification never suppresses a finding.</strong> You cannot verify your way out of a fixity mismatch.</li>
</ul>
<h3><code>source</code> and prov's <code>sources</code></h3>
<p><code>source</code> stays a free-form human string — <code>Grandma's shoebox, box 2</code> is not a path and never will be. It is the narrow case of prov's proposed <code>sources</code> list.</p>
<p>The part worth tracking is §6 of the proposal: extending prov's <code>fields</code> mechanism from term-valued to <strong>path-valued</strong> fields, so that a frontmatter string prov knows is a path gets rewrite-on-move, locator handling, and dangling-reference reporting for free. It is Phase 1, independently valuable, and fixes a live bug rather than adding a capability. When a document record's provenance needs to name <em>another document in the workspace</em> — a finding aid, an accession record, a parent collection — that belongs in a path-valued <code>sources</code> field, not in <code>source</code>, and not in a new Diaryx-specific key.</p>
<h2>Identifiers</h2>
<p>Identity is <a href="https://github.com/diaryx-org/prov">prov</a>'s, not Diaryx's. This spec earlier described a hand-rolled ID index (<code>Meta/Ids.md</code>, reached through a Config indirection); prov settled the question first and differently, and that design was never built. What follows is the layer Diaryx actually runs on.</p>
<p>prov treats identity as a <em>strictly-additive</em> layer over a workspace that already works on paths alone: the graph, traversal, and mutation layers never dereference an ID, and turning identity off changes nothing about how a record is stored or linked. IDs are <strong>minted at registration</strong> rather than derived — an unregistered document has no opaque ID at all and is addressed by path. Two config axes govern it, both set in the vault's <code>config.yaml</code>:</p>
<ul>
<li><code>identity: none | lazy | eager</code> — when an ID is minted. <code>lazy</code> (prov's default) registers on link-by-id or publish, keeping the registry to the minimal set something external depends on. Diaryx runs <code>eager</code>, which also registers on create: stable identity from birth, at the cost of a registry entry per document.</li>
<li><code>id_storage: registry | frontmatter | both</code> — where a registered ID lives. Diaryx runs <code>both</code>: each document carries its own <code>id</code> field and the registry document is a rebuildable cache. Frontmatter storage is what makes identity move- and copy-robust — the ID travels with the file, which is exactly what an artifact and its card copied out of the workspace need.</li>
</ul>
<p>The registry is a first-class member of the workspace, discovered through prov's <code>registry</code> pointer relation off the root. It is not a <code>Meta/</code> convention, and nothing in this spec should assume its path.</p>
<p>What remains Diaryx's is what <em>publication</em> means. Publication turns a registered ID into a permanent promise: at publish time the file receives a <code>permalink</code> frontmatter key holding the full URL with the ARK inside, in the canonical bare-<code>ark</code> form served by the site proxy (e.g. <code>permalink: https://diaryx.org/ark/dxg6h4ncm/4k2ph9t</code>, blades illustrative; the <code>ark:99999</code> prefix form is accepted as an alias). The ARK's workspace blade is the vault's prov <code>workspace_id</code>, and its <strong>file blade is the document's prov id</strong> — prov and <code>diaryx_ark</code> mint the same 6-random-plus-check shape over the same alphabet, so publication mints nothing per file and stores no second identifier. The ID is thereby recorded redundantly — in the document, in the registry, and in the server-side publish record — and must never be reused or reassigned.</p>
<p>The ARK envelope itself (NAAN, <code>dx</code> shoulder, check character, <code>.&lt;FILE&gt;</code>/<code>?&lt;QUERY&gt;</code>/<code>#&lt;CALLOUT&gt;</code> suffixes) is specified in the <a href="https://main.diaryx.org/diaryx/docs/ROADMAP.html">ROADMAP</a>; the alphabet and blade lengths are <code>diaryx_ark</code>'s, which follows prov's minter.</p>
<h2>Import contract</h2>
<p>Every importer emits document records. Import is a first-class workspace crate (<code>crates/diaryx_import</code>), not a plugin — the Extism stack that once held it was removed in <code>archive/tauri-web-1.6.1</code>, and the crate archived alongside it targeted the since-deleted <code>diaryx_core</code>. Its parsers are pure (<code>bytes -&gt; records</code>) and port forward; its writer does not, because it emits the Markdown card this spec no longer describes.</p>
<p>The contract:</p>
<ul>
<li><code>ImportedEntry</code> → an entry file (title, date, body, extra frontmatter), for born-digital text with no artifact</li>
<li><code>ImportedAttachment</code> → an artifact written through <code>Workspace::import_attachment</code>, which places the payload and lets prov mint the sidecar; the importer then stamps provenance onto that sidecar</li>
<li>Importers that recover text from an artifact (OCR, speech-to-text) emit a transcription file with <code>transcription_status: draft</code>, linked from the sidecar's <code>transcription:</code></li>
<li>Importers populate provenance keys when the source format provides them (email headers → <code>people</code>, EXIF origin date → <code>date_of_document</code>, etc.), and write <code>date_of_document: unknown</code> when the source offers no date for the original — never today's date, and never a date inferred from <code>created</code></li>
</ul>
<p>Nothing an importer writes may claim more than it knows. Deterministic decodes of born-digital originals (e.g. the text part of an email) may enter as <code>transcription_status: verified</code>; OCR and speech-to-text must enter as <code>draft</code>, per the lifecycle above.</p>
<h2>Future directions (deliberately deferred)</h2>
<ul>
<li><strong>Entity pages</strong>: <code>people</code>/<code>places</code> should eventually be links to entity pages rather than bare strings. Bare strings are forward-compatible with this (a string can be upgraded to a link), so start simple.</li>
<li>Transcription layer typing (verbatim vs. normalized) — needs real usage first.</li>
<li>Page-level mapping between multi-page artifacts and transcript sections.</li>
</ul>
]]></content>
  </entry>
  <entry>
    <title>Privacy Policy</title>
    <link href="https://main.diaryx.org/diaryx/privacy.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/privacy.html</id>
    <published>2026-03-30T00:00:00-06:00</published>
    <updated>2026-08-30T08:38:00Z</updated>
    <summary>Effective Date: August 30, 2026
This Privacy Policy describes how Diaryx (&amp;quot;we&amp;quot;, &amp;quot;us&amp;quot;) collects, uses, and protects your information when you use our applications and services (the &amp;quot;Service&amp;quot;).
The short version
Diaryx is local-first, and there is no c</summary>
    <content type="html"><![CDATA[<p><strong>Effective Date: August 30, 2026</strong></p>
<p>This Privacy Policy describes how Diaryx (&quot;we&quot;, &quot;us&quot;) collects, uses, and protects your information when you use our applications and services (the &quot;Service&quot;).</p>
<h2>The short version</h2>
<p>Diaryx is local-first, and <strong>there is no cloud sync</strong>. Your notes are files in a folder on your own device. We never receive them.</p>
<p>The only content that reaches our servers is content you explicitly publish. Everything below is mostly about that, and about the small amount of account data needed to run it.</p>
<p>Of that, the part you publish <strong>privately</strong> — a site behind a share link or a password — is encrypted on your device before it is uploaded. We store it, serve it, and cannot read it.</p>
<h2>1. Information We Collect</h2>
<h3>Information You Provide</h3>
<ul>
<li><strong>Email address:</strong> Used to create your account and to sign you in by emailed link or code.</li>
<li><strong>Device name:</strong> Your device's own name (for example &quot;Adam's iPhone&quot;) is sent when you sign in, so registered devices are recognizable in your account settings. You can rename or remove them there.</li>
<li><strong>Published content:</strong> Notes and attachments you choose to publish are uploaded to our servers and served at the audience level you configure. An audience you publish <strong>publicly</strong> is uploaded as ordinary web pages, which we can read because anyone can. An audience you put behind a share link or a password is <strong>encrypted on your device first</strong>, and what we receive is ciphertext under a key we are never sent — see §3.</li>
<li><strong>Custom domains:</strong> Any domain name you register with us for a published site.</li>
<li><strong>Audience passwords:</strong> If you password-protect an audience, the password itself never leaves your device. Your device runs it through Argon2id and sends us a hash of the result, which is what we compare a reader's attempt against. We store that hash and the (public) Argon2id salt and cost parameters a reader's browser needs to repeat the same derivation.</li>
</ul>
<h3>Information Collected Automatically</h3>
<ul>
<li><strong>Device identifier:</strong> A locally-generated device ID, created by the app to identify your sign-in session. It is not derived from any hardware identifier.</li>
<li><strong>Device signing key (public half):</strong> The app generates a signing key on each device and keeps the private half in that device's Keychain; it never leaves the device. The <strong>public</strong> half is sent when you sign in and recorded against the device, so that device can sign in again by proving it holds the key rather than by a new email code, and so readers of your published sites can check that what they received was signed by your device. Removing the device from your account settings removes its key with it. The key is generated by the app and is not derived from any hardware identifier.</li>
<li><strong>Request metadata:</strong> Because the Service runs on Cloudflare's network, Cloudflare processes the metadata of every request to it, including your IP address, timestamp, and user-agent string, and retains invocation logs under its own retention policy. We do not keep application logs of request contents.</li>
<li><strong>Usage counters:</strong> Aggregate counts of storage used and sites published, so your plan limits can be enforced and shown to you.</li>
</ul>
<h3>Payment Information</h3>
<p>Payment is processed entirely by Stripe (web) or Apple (iOS/macOS). <strong>We never see or store your card details.</strong> We store only the identifiers those providers give us to recognize your subscription: a Stripe customer and subscription ID, or an Apple original transaction ID.</p>
<h3>Information We Do NOT Collect</h3>
<ul>
<li><strong>Your unpublished notes.</strong> They are never transmitted to us. We have no copy of them and could not produce one.</li>
<li>We do not use analytics or tracking SDKs.</li>
<li>We do not collect browsing history, location data, or contacts.</li>
<li>We do not sell or share your personal data with third parties for advertising.</li>
</ul>
<h2>2. How We Use Your Information</h2>
<ul>
<li><strong>Authentication:</strong> Your email address is used to send sign-in links and codes.</li>
<li><strong>Publishing:</strong> Content you publish is stored and served to the audience you configure. Public content is, by design, available to anyone who has the URL.</li>
<li><strong>Custom domains:</strong> Your domain names are used to route requests to your site and are registered with Cloudflare so a TLS certificate can be issued for them. Certificate issuance makes a domain name publicly logged in Certificate Transparency logs, which is inherent to HTTPS and not specific to Diaryx.</li>
<li><strong>Billing:</strong> See <a href="https://stripe.com/privacy">Stripe's Privacy Policy</a> and <a href="https://www.apple.com/legal/privacy/">Apple's Privacy Policy</a>.</li>
<li><strong>Enforcing plan limits:</strong> Usage counters are compared against your plan's limits.</li>
<li><strong>Service operation:</strong> Request metadata is used for debugging, rate limiting, security monitoring, and reliability.</li>
</ul>
<p><strong>We never use your content to train AI models.</strong> Diaryx does not send your notes to any AI provider on its own initiative. Where the Service offers an optional AI-assisted feature, content is sent to the model provider only for the specific request you invoke, and only when you invoke it. (As of July 30, 2026, no AI-assisted content is available in the Service, optional or otherwise.)</p>
<h2>3. Data Storage and Security</h2>
<ul>
<li>The Service runs entirely on Cloudflare. The API is a Cloudflare Worker reached at <code>app.diaryx.org/api</code>.</li>
<li>Account and publishing metadata — your email address, devices, workspaces, sites, domains, and usage counters — is stored in a Cloudflare D1 database.</li>
<li>Published content and attachments are stored in Cloudflare R2. The mapping from a hostname to the site it serves is stored in Cloudflare KV.</li>
<li>Data is encrypted in transit (TLS).</li>
<li><strong>A public site is stored in the clear.</strong> It is stored so that it can be served, which means it is readable by our infrastructure, and it is meant to be readable by anyone with the address.</li>
<li><strong>A private site is encrypted before we receive it.</strong> When an audience has a share link or a password on it, your device renders and encrypts that audience's pages (AES-256-GCM) under a key derived from a secret generated on your device, and uploads only the result. We never receive that key and cannot derive it. Object names are blinded too, so the filenames do not disclose what the pages are. A reader gets the key from the link you sent them — carried in the fragment of the URL, which browsers do not transmit to a server — or by deriving it from the password they type.</li>
<li><strong>What we can still see about a private site</strong>, because hosting it requires it: how many objects it has, how large each is (padded into buckets), when you published, which audience an object belongs to, and the fact that a given audience has a gate at all.</li>
<li>The account data in §1 — your email address, devices, domains, and usage counters — is <em>not</em> covered by that encryption. It is ordinary stored data.</li>
<li>We implement reasonable security measures, but no method of transmission or storage is 100% secure.</li>
</ul>
<h2>4. Data Retention</h2>
<ul>
<li>Your published content and account data are retained as long as your account is active.</li>
<li><strong>Unpublishing</strong> removes content from our servers. It may briefly persist in caches.</li>
<li><strong>Deleting your account</strong> removes your account record, your published sites, your stored attachments, and your domain mappings. Deletion is attempted outside-in and any step that fails is logged and re-swept; your account record itself is not deleted unless it can be deleted.</li>
<li>Deleting your account does not touch the files on your own devices. Your notes remain yours and remain where they are.</li>
<li>Invocation logs are retained by Cloudflare under its own retention policy, not ours.</li>
</ul>
<h2>5. Third-Party Services</h2>
<p>We use the following third-party services:</p>
<table>
<thead>
<tr>
<th>Service</th>
<th>Purpose</th>
<th>Data Shared</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cloudflare</td>
<td>All hosting: compute (Workers), database (D1), object storage (R2), domain routing (KV), CDN, and TLS</td>
<td>Everything the Service stores or serves, plus request metadata. A private site's pages reach Cloudflare already encrypted, so what is shared there is ciphertext</td>
</tr>
<tr>
<td>Resend</td>
<td>Sending sign-in emails</td>
<td>Email address</td>
</tr>
<tr>
<td>Stripe</td>
<td>Payment processing (web)</td>
<td>Email address, payment details you enter with Stripe</td>
</tr>
<tr>
<td>Apple</td>
<td>Payment processing (iOS/macOS)</td>
<td>Apple ID, payment details you hold with Apple</td>
</tr>
</tbody>
</table>
<p>We do not sell your data to third parties.</p>
<h2>6. Your Rights</h2>
<p>You may:</p>
<ul>
<li><strong>Access your data:</strong> Your notes are files on your own disk, readable with or without Diaryx. Your account data — email, registered devices, workspaces, published sites, storage used — is shown in the app's account settings.</li>
<li><strong>Export your data:</strong> Diaryx stores notes as standard Markdown files with YAML frontmatter, so there is nothing to export from — you already have them. The <code>diaryx export</code> command can additionally produce an audience-filtered copy of a vault.</li>
<li><strong>Correct your data:</strong> Device names and site settings can be edited in the app. For anything else, contact us.</li>
<li><strong>Delete your data:</strong> Delete individual notes at any time; unpublish a site to remove it from our servers; delete your account to remove your server-side data entirely.</li>
<li><strong>Cancel your subscription:</strong> At any time, via your device's subscription management (Apple) or the Manage Billing page in Settings (Stripe).</li>
</ul>
<p>If you are in the EU/EEA or the UK, you also have rights under the GDPR including rectification, erasure, data portability, restriction of processing, and the right to lodge a complaint with your supervisory authority. To exercise any of them, contact us at the address below.</p>
<h2>7. Children's Privacy</h2>
<p>The Service is not directed at children under the age of 13. We do not knowingly collect personal information from children under 13. If you believe we have collected such information, please contact us so we can delete it.</p>
<h2>8. Changes to This Policy</h2>
<p>We may update this Privacy Policy from time to time. If we make material changes, we will notify you via the Service or by email. The &quot;Effective Date&quot; at the top indicates when the policy was last updated.</p>
<h2>9. Contact</h2>
<p>If you have questions about this Privacy Policy, contact us at <a href="mailto:contact@diaryx.org">contact@diaryx.org</a>.</p>
]]></content>
  </entry>
  <entry>
    <title>Terms of Service</title>
    <link href="https://main.diaryx.org/diaryx/terms.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/terms.html</id>
    <published>2026-03-30T00:00:00-06:00</published>
    <updated>2026-09-07T00:00:00Z</updated>
    <summary>Effective Date: August 1, 2026
These Terms of Service (&amp;quot;Terms&amp;quot;) govern your use of Diaryx, including the Diaryx apps for macOS and iOS, and the diaryx command-line tool (collectively, the &amp;quot;Service&amp;quot;). By using the Service, you agree to these Terms.
1. Descripti</summary>
    <content type="html"><![CDATA[<p><strong>Effective Date: August 1, 2026</strong></p>
<p>These Terms of Service (&quot;Terms&quot;) govern your use of Diaryx, including the Diaryx apps for macOS and iOS, and the <code>diaryx</code> command-line tool (collectively, the &quot;Service&quot;). By using the Service, you agree to these Terms.</p>
<h2>1. Description of Service</h2>
<p>Diaryx is a local-first note-taking and journaling application. Your notes are plain files in a folder you choose on your own device; the app reads and writes that folder directly.</p>
<p>An account is optional. It exists to enable the online features:</p>
<ul>
<li><strong>Publishing</strong> — turning some or all of a workspace into a website, served on a free <code>*.diaryx.org</code> subdomain or on a custom domain you own</li>
<li><strong>Audience gates</strong> — publishing at the visibility you choose, including public, link/token-protected, and password-protected</li>
</ul>
<p>The Diaryx server is also available to self-host under the license in Section 7.</p>
<h3>No cloud sync</h3>
<p><strong>Diaryx does not currently offer cloud sync.</strong> Nothing leaves your device except what you explicitly publish. Keeping a vault available across your own devices is something you arrange yourself — for example by putting the folder in iCloud Drive or another file-syncing service of your choosing — and any such service is governed by its own terms, not these.</p>
<p>If we add a sync feature later, we will describe it here before it applies to you.</p>
<h2>2. Accounts</h2>
<p>To use the online features you must create an account with a valid email address. Sign-in is by emailed link or code. You are responsible for maintaining the security of your account and of the devices signed in to it.</p>
<p>Each account may have a limited number of registered devices signed in at once. This ceiling is a security backstop against a leaked or shared credential, not a plan feature, and is set well above what any individual would reach. You can review and remove your registered devices in the app's account settings.</p>
<h2>3. Subscription Plans</h2>
<p>Storage figures below are <strong>decimal</strong>: 1 GB means 1,000,000,000 bytes.</p>
<p><strong>Writing is never counted.</strong> The storage figures below apply to published photos and files only. The text you publish — your pages, and the rendered site made from them — does not count against any plan's storage, on any plan, however much of it there is.</p>
<h3>Free Plan</h3>
<p>The Free plan includes:</p>
<ul>
<li>1 workspace</li>
<li>1 published site</li>
<li>1 circle: the people you share that site with, or its public address</li>
<li>40 MB of published photos and files, each up to 10 MB</li>
<li>A free <code>*.diaryx.org</code> subdomain for your site</li>
</ul>
<h3>Diaryx Plus</h3>
<p>Diaryx Plus costs $4.99/month (USD) and includes:</p>
<ul>
<li>Up to 10 workspaces</li>
<li>Up to 10 published sites</li>
<li>Up to 50 circles</li>
<li>25 GB of published photos and files, each up to 100 MB</li>
<li>Up to 10 custom domains</li>
</ul>
<p>The custom-domain and circle allowances belong to your account as a whole, not to each workspace. Free <code>*.diaryx.org</code> subdomains are not counted against the domain allowance.</p>
<p>Accounts created before the Free plan's photo-and-file allowance was reduced from 200 MB keep the allowance they signed up under.</p>
<p>If your Plus subscription ends, nothing you have published is taken down. Your sites stay online and readable, your workspaces stay connected, and you can keep publishing what you write. What the Free plan does not include — additional workspaces, sites and domains, and photos and files beyond its allowance — you can no longer add until you subscribe again.</p>
<p>The price shown at the point of purchase is the price that applies. Plus subscriptions renew monthly until cancelled. You may cancel at any time:</p>
<ul>
<li><strong>Apple In-App Purchase (iOS/macOS):</strong> Via Settings &gt; Apple ID &gt; Subscriptions on your device.</li>
<li><strong>Stripe (web):</strong> Via the Manage Billing page in Settings.</li>
</ul>
<p>Cancelling stops future renewals; your Plus features remain active until the end of the current billing period. Refunds for purchases made through Apple are handled by Apple under its own policies.</p>
<p>We may change plan limits and pricing. If a change reduces what your existing plan includes, or raises its price, we will tell you before it takes effect.</p>
<h2>4. Your Content</h2>
<p>You retain all rights to the content you create with Diaryx. We do not claim ownership of your notes, entries, or attachments.</p>
<p>Content stored only on your own device is never transmitted to us. When you publish, the content you selected is uploaded to our servers and served at the audience level you chose. Removing it from your site removes it from our servers; it may persist briefly in caches and backups.</p>
<p>You are the publisher of anything you publish through the Service, and you are responsible for having the rights to publish it.</p>
<h2>5. Acceptable Use</h2>
<p>You agree not to:</p>
<ul>
<li>Use the Service to store or distribute illegal content</li>
<li>Publish content you do not have the right to publish</li>
<li>Attempt to interfere with or disrupt the Service</li>
<li>Use the Service to send spam or unsolicited messages</li>
<li>Reverse-engineer the Service beyond what is permitted by applicable law</li>
<li>Exceed reasonable usage limits or abuse the Service infrastructure</li>
</ul>
<p>We may remove published content, or suspend publishing for an account, in response to a valid legal complaint or a clear violation of this section, with notice when practicable.</p>
<h2>6. Custom Domains</h2>
<p>If you point a domain you own at the Service, you are responsible for that domain's registration and DNS. We provision and renew a TLS certificate for it while it is registered with us and pointed at us. Removing the domain from your account stops that.</p>
<h2>7. Intellectual Property</h2>
<p>The Diaryx software is closed source. All rights are reserved by Adam Harris as of 2026. Your use of the software is subject to that license, which means you may not copy, modify, reverse-engineer, or otherwise tamper with the Diaryx binary or its source code, though you retain all rights to the content you provide and interact with through the Service. Diaryx workspaces are based on the open-source software Prov, and users may alternatively interact with their workspaces through the Prov command-line interface. For more details, see LICENSE.</p>
<h2>8. Termination</h2>
<p>You may delete your account at any time. We may suspend or terminate your access to the Service if you violate these Terms, with notice when practicable.</p>
<p>Upon termination, your published sites are taken down and your uploaded data may be deleted from our servers. The files on your own devices are not affected — deleting your account does not delete your notes.</p>
<h2>9. Disclaimers</h2>
<p>The Service is provided &quot;as is&quot; without warranties of any kind, express or implied. We do not guarantee that the Service will be uninterrupted or error-free.</p>
<p><strong>You are responsible for backing up your own data.</strong> Diaryx has no copy of anything you have not published.</p>
<h2>10. Limitation of Liability</h2>
<p>To the maximum extent permitted by law, Diaryx and its operators shall not be liable for any indirect, incidental, special, consequential, or punitive damages, or any loss of data, profits, or goodwill, arising from your use of the Service.</p>
<p>Our total liability for any claim arising from the Service is limited to the amount you paid us in the 12 months preceding the claim.</p>
<h2>11. Apple</h2>
<p>For apps obtained through the App Store: Apple is not a party to these Terms and has no obligation to provide support or maintenance for the Service. Apple is not responsible for addressing any claim relating to the app, and Apple's maximum liability to you in the event of a defect is the purchase price, if any. You represent that you are not located in a country subject to a U.S. Government embargo and are not on any U.S. Government restricted-parties list.</p>
<p>Apple and its subsidiaries are third-party beneficiaries of these Terms, and upon your acceptance of these Terms Apple will have the right (and will be deemed to have accepted the right) to enforce these Terms against you as a third-party beneficiary. We, not Apple, are solely responsible for the app, its content, and any maintenance or support for it, and for addressing any claims relating to it.</p>
<h2>12. Changes to These Terms</h2>
<p>We may update these Terms from time to time. If we make material changes, we will notify you via the Service or by email. Continued use of the Service after changes take effect constitutes acceptance of the updated Terms.</p>
<h2>13. Governing Law</h2>
<p>These Terms are governed by the laws of the State of Utah, United States, without regard to conflict of law principles.</p>
<h2>14. Contact</h2>
<p>If you have questions about these Terms, contact us at <a href="mailto:contact@diaryx.org">contact@diaryx.org</a>.</p>
]]></content>
  </entry>
  <entry>
    <title>ROADMAP</title>
    <link href="https://main.diaryx.org/diaryx/docs/ROADMAP.html" rel="alternate"/>
    <id>https://main.diaryx.org/diaryx/docs/ROADMAP.html</id>
    <published>2025-12-05T12:06:55-07:00</published>
    <updated>2026-08-17T01:38:55Z</updated>
    <summary>Diaryx is currently at version v2.0.0. The mission is archival: making a personal &amp;quot;Papers Project&amp;quot; — gather, transcribe, annotate, publish — accessible to anyone (see PHILOSOPHY).
Direction (planning session, 2026-07-03)
The next phase centers on the gather/import w</summary>
    <content type="html"><![CDATA[<p>Diaryx is currently at version v2.0.0. The mission is archival: making a personal &quot;Papers Project&quot; — gather, transcribe, annotate, publish — accessible to anyone (see <a href="https://main.diaryx.org/diaryx/docs/PHILOSOPHY.html">PHILOSOPHY</a>).</p>
<h2>Direction (planning session, 2026-07-03)</h2>
<p>The next phase centers on the <strong>gather/import wedge</strong>: the person who most wants a personal Papers Project has <em>existing</em> material — a shoebox of letters, old journals, exported blogs, scattered Google Docs — not just new writing. Diaryx should be the best tool for getting that material in, transcribed, and annotated.</p>
<p>The unifying piece is the <strong>document record</strong>: a specified archival unit (artifact + catalog card + transcription + annotation) that every importer targets, annotation lives in, and identifiers point at. See the <a href="https://main.diaryx.org/diaryx/docs/Document Record Spec.html">Document Record Spec</a>.</p>
<h2>Near-term priorities</h2>
<h3>1. Document record spec</h3>
<p>Finalize the <a href="https://main.diaryx.org/diaryx/docs/Document Record Spec.html">Document Record Spec</a>: attachment notes as catalog cards (typed <code>transcription:</code> links, provenance metadata), transcription files with a <code>draft → needs_review → verified</code> lifecycle, annotation via footnotes and sibling commentary files (no standoff/offset anchoring — ever).</p>
<p>The remaining open piece is provenance. <code>transcription_status: verified</code> is currently a bare enum, so it survives an edit to the transcript it describes — a stale assurance sitting in frontmatter. prov's provenance proposal fixes this by binding a verification to the fixity digest it was made against, and the spec's Provenance section records the intended layering: <code>transcription_status</code> stays the workflow position, prov's <code>verified</code> becomes the attributed claim that backs its terminal state. That proposal is an early draft whose Phase 0 is carry-only, so this waits on prov rather than growing a Diaryx-specific duplicate.</p>
<h3>2. Gather: photo/scan → OCR → document record</h3>
<p>The first new importer and the flagship demo: photograph a physical document, get artifact + draft transcript + catalog card in one gesture. Machine transcripts enter as <code>transcription_status: draft</code>, giving users the archivist workflow (gather → transcribe → verify → annotate) rather than a black-box import.</p>
<p>Then:</p>
<ul>
<li><strong>Done.</strong> Build import as a first-class workspace crate (<code>crates/diaryx_import</code>). This was written as &quot;promote import from an extism-only plugin&quot;, which was no longer the situation: the Extism stack and the old <code>diaryx_import</code> were both removed in <code>archive/tauri-web-1.6.1</code>, and that crate targeted the since-deleted <code>diaryx_core</code>. Its parsers (Day One, email, markdown) are pure <code>bytes -&gt; records</code> and port forward; its writer did not, since it emitted the Markdown catalog card the <a href="https://main.diaryx.org/diaryx/docs/Document Record Spec.html">Document Record Spec</a> no longer describes. There was no plugin to adapt.</li>
<li><strong>Done.</strong> Lead with a <strong>directory importer</strong> — a folder of scans and documents is the literal shoebox, and it exercises the artifact + card path end to end. It is reachable everywhere it should be: <code>diaryx import &lt;folder&gt;</code> (with <code>--dry-run</code>), and &quot;Bring In What You Have…&quot; in the app's add menu and Browse's empty state. The app asks twice — a scan says what would happen, and only then does anything get written — because an import of several hundred documents has no undo. <strong>Still to do:</strong> retrofit the ported parsers (Day One, email, markdown) to emit document records, which validates the spec against born-digital inputs</li>
<li>Write the transcription half: <code>transcribe_page</code> already returns a draft, and <code>diaryx_ffi</code> defers writing it into the vault as &quot;the workspace's job&quot;. Nothing does that job yet</li>
<li>Widen by shoebox-frequency: Google Docs/Drive, blog exports (WordPress/RSS), Apple Notes</li>
</ul>
<h3>3. Identifiers: prov's registry, permanence at publish time</h3>
<p><strong>Done, and not the way this section originally planned it.</strong> The plan was a Diaryx-owned ID index linked from <code>Meta/Config.md</code>; prov settled identity first, and the vault runs on that instead. Identity is a strictly-additive layer over a path-only workspace, IDs are minted at registration rather than derived, and two config axes govern it — Diaryx sets <code>identity: eager</code> (register on create) and <code>id_storage: both</code> (each document carries its own <code>id</code>, with prov's registry document as a rebuildable cache). Frontmatter storage is what makes a record folder copied out of the vault keep its identity.</p>
<p>What stayed Diaryx's is the meaning of publication:</p>
<ul>
<li><strong>Published files</strong> get a <code>permalink: &lt;full URL with the ARK inside&gt;</code> in their frontmatter at publish time. Publication is the moment an ID becomes a permanent promise: recorded in the document, in the registry, and in the server-side publish record.</li>
<li>The ARK's workspace blade is the vault's prov <code>workspace_id</code>; its <strong>file blade is the document's prov id</strong>. The two minters agree by construction, so publishing mints nothing per file and stores no second identifier.</li>
</ul>
<p>ARK minting is therefore a <strong>publish-time contract</strong> layered over prov identity, not a filesystem feature.</p>
<h3>4. Trust artifacts</h3>
<p>Archival trust for a small project comes from the exit story, not from the software surviving:</p>
<ul>
<li>Publish the format specs (frontmatter conventions, document record, ARK scheme) as open documents others could implement — formats outlive apps</li>
<li>Make &quot;if Diaryx vanishes tomorrow, you lose nothing&quot; a marketing centerpiece</li>
<li>Design ARK resolution to degrade gracefully: the ID mapping ships inside the workspace itself, and eventual NAAN registration/N2T means resolution can outlive diaryx.org</li>
</ul>
<h2>ARK identifier format</h2>
<p><code>ark:99999/dxXXXXXXC/XXXXXXC[.&lt;FILE&gt;][?&lt;QUERY&gt;][#&lt;CALLOUT&gt;]</code></p>
<p>Eventually Diaryx as an organization will register for a NAAN, which will replace <code>99999</code>. <code>dx</code> is the &quot;shoulder&quot; of the ID, which allows for changing the ID format in the future if needed. Each capital <code>X</code> is an extended digit from the 29-character NOID alphabet — digits plus consonants, with no vowels (avoiding accidental words), no <code>l</code> (ambiguous with <code>1</code>), and no <code>y</code>:</p>
<p><code>0 1 2 3 4 5 6 7 8 9 b c d f g h j k m n p q r s t v w x z</code></p>
<p>Each capital <code>C</code> is a NOID check character calculated from the preceding characters, to catch transcription errors. So a workspace blade is 9 characters (<code>dx</code> + 6 + check) and a file blade is 7 (6 + check).</p>
<p>A blade may contain — and begin with — a digit, so anything writing one into metadata has to keep it a string, or YAML/JSON scalar inference turns <code>0123456</code> into a number and loses the leading zero.</p>
<p>This alphabet is not a free choice. A file blade <em>is</em> a prov id (see §3), so <code>diaryx_ark</code> must spell ids exactly as prov's minter does or every published permalink fails its own validation. Both previously used <code>betanumeric</code> (<code>bcdfghjkmnpqrstvwxyz23456789</code>); prov moved to the canonical NOID alphabet so its check character would agree with a real NOID minter, and Diaryx followed. That is a <strong>hard break in both directions</strong>, deliberately not softened: the alphabets differ in membership (<code>y</code> is betanumeric-only, <code>0</code> and <code>1</code> are xdigit-only), and even where characters are shared the ordinals differ, so the check character differs. Accepting both would leave a blade valid under either check — which is a blade whose check character has stopped detecting typos. ARKs minted and published before the change are invalidated by it.</p>
<p><code>.&lt;FILE&gt;</code> is a way of accessing different versions of the same file. <code>?&lt;QUERY&gt;</code> is a way of accessing metadata for a file. <code>#&lt;CALLOUT&gt;</code> is a client-only method of highlighting a specific portion of the content and isn't actually used by the server.</p>
<p>ARKs typically reserve <code>?info</code> and <code>?json</code>, as well as <code>??</code>. These are reserved alongside <code>content</code> for special query functionality rather than mapping literally to frontmatter metadata key names. To access a literal <code>info</code> or other reserved-name frontmatter key, a namespace like <code>?meta=info</code> or a leading dot like <code>?.info</code> is under consideration.</p>
<p>6 random characters is enough to identify a workspace for worldwide Diaryx usage (29^6 = 594,823,321), and the same width covers the files within one workspace. Both are minted randomly rather than sequentially — opaque for free, with no sequence to hide — and uniqueness is enforced by rejection at the caller. If usage somehow exceeds this, the <code>dx</code> shoulder can be changed to make a new ID format that allows for more room.</p>
<h1>OCFL Provenance</h1>
<p>Be able to store version history of a workspace via a OCFL implementation.</p>
]]></content>
  </entry>
</feed>
