A CLI for publishing standard.site documents to ATProto sequoia.pub

`publish` appends `atUri` at EOF, corrupting TOML frontmatter when a table precedes it (key gets nested into the table) #46

Closed h.olysh.it
Closed opened by h.olysh.it

Version: sequoia-cli 0.5.7

Environment: Hugo blog, TOML frontmatter (+++ delimiters), posts with a [cover] table.

Summary #

sequoia publish writes the atUri back to a post's frontmatter as a new line at the end of the frontmatter block. In TOML, a bare key after a [table] header belongs to that table — it does not return to the top level. So when frontmatter contains any table (e.g. PaperMod's [cover]), the appended atUri is parsed as a key inside that table rather than a top-level key. Downstream consumers that read top-level atUri (templates, the inject step, social cards) then see it as missing.

Steps to reproduce #

  1. A post with TOML frontmatter that ends with a table:

    +++
    title = "Example"
    coverImage = "static/covers/example.png"
    
    [cover]
      image = "/covers/example.png"
      alt = "…"
      hidden = true
    +++
    
  2. Run sequoia publish.

Actual result #

atUri is appended after the table, so it parses as cover.atUri:

   [cover]
     image = "/covers/example.png"
     alt = "…"
     hidden = true
   atUri = "at://did:plc:…/site.standard.document/…"   # ← nested under [cover]
   +++

Top-level atUri is empty. Any template/logic gating on it silently no-ops, with no error.

Expected result #

atUri should be written as a top-level key regardless of existing tables — e.g. inserted before the first table header, or set via a structure-aware TOML edit rather than a raw line append.

Impact #

  • Silent: no parse error, no warning. The post publishes to ATproto fine, but anything keying off frontmatter atUri (e.g. rendering a recommend/subscribe component, conditional logic, the inject correlation) breaks.
  • Affects every post whose frontmatter has a table before EOF. Posts with no table (flat frontmatter) are unaffected, which makes it look intermittent and hard to spot.
  • Symmetric risk for any future appended key, and likely the same in YAML/JSON frontmatter if the append isn't format-aware (the table-nesting failure is TOML-specific, but EOF-appending is fragile in general).

Suggested fix #

Parse the frontmatter into a structured document and set atUri as a top-level field, then re-serialize — instead of appending a raw line. If a lightweight approach is preferred, at minimum insert the key before the first [table]/[[array]] header within the frontmatter block.

Workaround #

Manually move the atUri line above any table header in the frontmatter (keeps it top-level), or express the table as a TOML inline table so there is no open table section for an appended key to fall into:

cover = { image = "/covers/example.png", alt = "…", hidden = true }
atUri = "at://…"   # appended at EOF, stays top-level

Parse the frontmatter into a structured document

Any suggestions how best to detect YAML vs. TOML vs. ??

Also note that you may not get the serialized form back in a minimal diff. On another project, we had to submit a PR to a transitive dependency to fix an issue that broke re-serialization then to the upstream dependency to get that update, then we could take it. Took a while.

Maybe a little fragile, but what if we write to the first empty line, shifting the empty line down i.e., there'll still be an empty line. YAML/TOML doesn't care about whitespace (you're the first I've seen indent TOML), so this may not work in all cases.

I see we do treat +++ as an indicator of TOML. Seems a little presumptuous. For example, cargo scripts use --- for front matter. I know that's irrelevant here, but I bring it up as an example of how different front matter markers could be used.

Still, if that's the current behavior, at least we could device whether to parse as YAML or TOML. Still, re-serializing may change more than expected e.g., order may not be preserved. In a lot of serializers, the order is based on the defined order of fields, not what is parsed.

If this becomes a problem you could assume that +++ is toml and --- is yaml but provide an override config option? I don't have enough scope to know what is more common here.

But the change looks good to me!

Sign up or Sign in to add to the discussion.