Skip to content

RFC: Listing extensions table, postponed - #51

Open
SafeShows wants to merge 6 commits into
KSAModding:mainfrom
ksamods-gg:main
Open

SafeShows wants to merge 6 commits into
KSAModding:mainfrom
ksamods-gg:main

Conversation

@SafeShows

@SafeShows SafeShows commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

What

Proposed an optional [extensions] table on authored files: namespaced key-value data no resolver, installer, or compatibility check may read.

Now postponed. Review established that the derived-view model accepted in #37 already covers every case this could name, and nobody could produce the one kind of fact the table would be needed for. The corrected design stays in the file so a future proposal starts from it rather than from this one's first draft.

RFC checklist

  • RFC number allocated and the filename matches the rfc: field in the front matter
  • Discussion thread linked in the front matter
  • Claims about game behavior cite a class and method
  • If this merges an acceptance: DECISIONS.md updated, status: Accepted, and any superseded RFC marked

Postponed is terminal, so this can merge; only Accepted takes a DECISIONS.md row. The third box is vacuous — this RFC makes no claim about game behavior, which was always the point.

What the latest commit resolved

Six [must fix] items from @Maximilian-Nesslauer's review, and the two that led to postponing:

  • Ownership. The check that content-index#34 implements for RFC 0048 gives write access to the content author, and nothing in it lets a consumer maintain live data inside somebody else's listing. Every consumer-side update would have to be submitted by an author with no reason to care. Now its own section, and one of the two reasons for postponing.
  • The One catalogue, several front ends #37 boundary. The original motivation had it backwards: a derived view keyed by listing id holds one copy, in the store whose owner maintains it. Both original examples argued for that model — the ksamods-gg field in content-index#49 is a back-reference to that site's own database record, so copying it in creates the second copy and a freshness problem, and accent never had a clear owner at all.
  • Packs excluded. A pack document is immutable per version, so an extension on it is frozen rather than live and the full allowance repeats per version in the snapshot. Excluding modpack was the smallest of the three ways out.
  • Size rule made exact. UTF-8 byte length of the parsed extensions value serialized as compact JSON, no insignificant whitespace. TOML comments, indentation, key order and the snapshot's two-space indent do not count.
  • Schema boundary is normative here. The companion pull request implements the Shape and Errors rules exactly and has no latitude to permit a free subtree, the way RFC 0048 depends on content-index#34. The old unresolved question that left it open is gone.
  • Snapshot question removed. spec/snapshot.md already answers it: every authored document appears verbatim and is sufficient offline, so the table appears there for every listing carrying one. A separate fetch would have to amend that contract and give up its one-fetch and offline guarantees.

Also from the first review round: the table is [extensions], not [metadata], since the whole file is metadata; the closed-schema starting position replaced the wrong [links] claim; and the icon/banner example is gone, since those are wanted by every client and belong to #45.

The filename still says listing-metadata so the review threads stay attached — rename at merge if you want the slug to match.

🤖 Generated with Claude Code

@SafeShows
SafeShows marked this pull request as ready for review September 6, 2026 10:04
@SafeShows
SafeShows requested a review from a team as a code owner September 6, 2026 10:04
@SafeShows SafeShows added rfc an RFC proposal or its tracking issue stage:proposed RFC is ready for review labels Sep 6, 2026

@Maximilian-Nesslauer Maximilian-Nesslauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the RFC draft.

I am not against a namespaced extension point but what I want changed is the motivation, the examples, and three rules that do not hold against the index as it runs today.

Comment thread rfcs/0051-listing-metadata.md Outdated
Comment thread rfcs/0051-listing-metadata.md Outdated
Comment thread rfcs/0051-listing-metadata.md Outdated
Comment thread rfcs/0051-listing-metadata.md Outdated
Comment thread rfcs/0051-listing-metadata.md Outdated
Comment thread rfcs/0051-listing-metadata.md Outdated

@Maximilian-Nesslauer Maximilian-Nesslauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the revision.

It addresses all six comments from my first review but the revised proposal exposes several contract problems that the first version did not make visible.

The largest one is the reason for putting consumer-private data into the canonical index at all.
Discussion #37 already puts service-local data in a derived view and makes that view reconstructible from the canonical listing id.
The real ksamods.gg field in KSAModding/content-index#49 is a back-reference to the site's own database record.
Copying that private record id into the canonical listing creates a second copy and a freshness problem instead of removing one.

The Borea accent example also needs a clearer ownership case because it is either Borea-local presentation data or a general author-selected presentation field.

The proposal also needs one answer for pack documents, an exact and computable size rule, and alignment with the existing snapshot contract.
The snapshot already carries every authored document verbatim and does not permit a client to fetch selected authored fields separately.
The schema shape is also already normative in the RFC, so the companion change cannot be left to choose a different shape.

Please also update the pull request title and body.
They still describe the old [metadata] proposal, repeat the old [links] claim, and list issues that the new commit resolved.

Comment thread rfcs/0051-listing-metadata.md Outdated
An optional `[extensions]` table on every authored file, holding namespaced key-value data that no resolver, installer, or compatibility check may read.

It is an extension point, not a field.
A client or an index puts data under a namespace it owns, every other consumer ignores it, and a key that several consumers converge on becomes a first-class field by RFC.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] The current ownership check, implemented in KSAModding/content-index#34 and described by proposed RFC 0048, does not let a client or an index maintain arbitrary live data in someone else's listing.

Please state who writes and updates an extension. If the consumer owns and changes the value, explain how it stays current without making the content owner submit every consumer-side update.

Comment thread rfcs/0051-listing-metadata.md Outdated
Comment on lines +31 to +35
ksamods.gg serves its own answer from its own API, Borea keeps a side table, and the same fact exists twice with no way to say which copy is current.
That is the position the whole of RFC 0031 was written to get out of, reintroduced one layer down.

Doing nothing does not stop consumers carrying extra data.
It decides only whether that data lives somewhere with rules, or in private stores nobody else can see.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] This conflicts with the boundary decided in discussion #37.

A derived view keeps service-local data in its own store and keys it by the canonical listing id.
The current field in KSAModding/content-index#49 is ksamods.gg's own database id, so copying it into the canonical listing creates the second copy and a new question about which copy is current.

Please give at least one concrete author-owned fact that must live in the canonical index but has exactly one consumer, or revise the motivation and the Do nothing alternative around the derived-view model we already accepted. Without that evidence, I do not see enough reason to weaken the closed schema.

Comment thread rfcs/0051-listing-metadata.md Outdated
Comment on lines +73 to +74
In the shared authored core of [RFC 0031](0031-content-metadata-format.md), so it applies to `mod`, `modpack`, `mod-loader`, and every type added later with no per-type work.
Optional everywhere; absent means nothing.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] Every authored file includes a pack version, but RFC 0031 makes each pack document immutable and the snapshot retains all pack versions.

An extension on a pack is therefore frozen per version, not live, and changing it requires a new pack version. It can also repeat the full allowance once for every version.

Please either exclude modpack, define the data as version-specific for packs, or change the pack model. The current rule conflicts with the live-data reason at line 94.

Changing the pack model might make sense here.

Comment thread rfcs/0051-listing-metadata.md Outdated
| Every direct child of `[extensions]` is a table. A scalar or array directly under `[extensions]` makes the file invalid. | Un-namespaced keys are how two consumers end up fighting over `accent`. Forcing the namespace makes a collision impossible rather than unlikely. |
| Namespace names follow RFC 0031's id rules, compared case-insensitively. | Reusing the id charset means no second naming scheme to specify, and it is already known to be safe on every platform. |
| A namespace need not be a listed id, and claiming one grants nothing. | The table names consumers, not content, and `borea` is not a mod. |
| The serialized `[extensions]` table is at most 4 KiB per listing. | Every byte lands in the snapshot RFC 0033 ships to every client, so an unbounded table is a cost paid mostly by people who never read it. |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] Please define the representation that this limit measures and resolve unresolved question 1 before approval.

The TOML source bytes, the parsed JSON value, compact JSON, and the indented snapshot bytes have different sizes, and TOML comments, whitespace.The schema check, snapshot builder, and other implementations need one exact byte sequence and encoding.

Comment thread rfcs/0051-listing-metadata.md Outdated

1. **Is 4 KiB the right cap, and is it per listing or per namespace?** Per listing is simpler and makes namespaces compete for it, which may be the wrong incentive.
2. **Should namespaces be registered anywhere?** Unowned is simplest and matches the ecosystem's size; a squatted namespace has no remedy today.
3. **How far does the schema open?** Permitting `extensions` with typed namespaces still validates more than permitting a free subtree, and the companion pull request has to pick one.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] This is not an open choice after the Shape and Errors sections.

Those sections require extensions to be a table, each direct child to be a table with a valid id as its name, and case-insensitive duplicates to fail. A companion schema that permits a free subtree at the extensions level would contradict those rules.

Please state the schema boundary here and make the companion pull request implement it, or change the earlier normative rules.

Comment thread rfcs/0051-listing-metadata.md Outdated
1. **Is 4 KiB the right cap, and is it per listing or per namespace?** Per listing is simpler and makes namespaces compete for it, which may be the wrong incentive.
2. **Should namespaces be registered anywhere?** Unowned is simplest and matches the ecosystem's size; a squatted namespace has no remedy today.
3. **How far does the schema open?** Permitting `extensions` with typed namespaces still validates more than permitting a free subtree, and the companion pull request has to pick one.
4. **Does the snapshot carry `[extensions]` for every listing, or may a client fetch it separately?** Small enough not to matter now, but it is the first field whose readers are a strict subset of clients.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] spec/snapshot.md already answers this.

Every authored document appears verbatim in the snapshot, the snapshot is sufficient for offline use, and per-file fetch is only a secondary tooling path. An extensions table therefore appears in the snapshot for every listing and every pack version that carries it.

Please state that result in the reference section and remove this unresolved question. If the proposal instead wants a separate client fetch, it must amend the snapshot contract and explain the loss of its one-fetch and offline guarantees.

It might make sense to reduce the snapshot size? Example calculations if there are any meaningful savings would be nice.

@SafeShows SafeShows changed the title RFC: Listing metadata bag RFC: Listing extensions table, postponed Sep 7, 2026

@Maximilian-Nesslauer Maximilian-Nesslauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the new revision.

Postponing the proposal is a reasonable outcome but i dont want to dismiss it.
The new text addresses the substance of my previous.

I still request changes because the postponed record is internally inconsistent in some places.

The summary still applies the table to every authored file, while the reference section excludes modpack.
The guide and rules require a consumer to own a namespace, while the same RFC says namespaces are unowned and leaves registration unresolved.
The size rule also does not define how TOML values that have no direct JSON representation are converted, so different implementations can still count different byte sequences.

Finally, the RFC says that none of the postponed design is normative, but the schema section immediately says the rules are normative.

For a postponed RFC, this should use conditional language and state what a future companion change would have to do if the proposal is reopened.


## Summary

An optional `[extensions]` table on every authored file, holding namespaced key-value data that no resolver, installer, or compatibility check may read.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] The summary still says every authored file, but the reference section limits the table to mod and mod-loader and explicitly excludes modpack.

Please use the same scope here. Also, RFC 0031 defines the shared authored core as the fields carried by every authored document, so line 89 should not call a field that excludes packs part of that shared core.

Comment on lines +75 to +76
Each direct child of `[extensions]` is a namespace named after the consumer that owns it.
That consumer reads its own namespace and ignores every other; a client that knows none of them loses nothing.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] The design cannot require a namespace owner while it also states that namespaces are unowned.

This paragraph and line 117 require a consumer that owns the namespace, but line 103 says that claiming a name grants nothing, line 144 calls namespaces unowned, and unresolved question 3 leaves registration open.

Please either define how a consumer owns a namespace or replace the ownership rule with a rule that does not need an owner, such as a consumer reading only a namespace that it explicitly recognizes.

Comment on lines +108 to +113
One representation, so the schema check, the snapshot builder and any other implementation compute the same number:

**The UTF-8 byte length of the parsed `extensions` value serialized as compact JSON, with no insignificant whitespace.**

TOML comments, indentation, and key order do not count, and neither does the two-space indentation `spec/snapshot.md` applies when the value reaches the snapshot.
Whether 4 KiB is the right number, and whether it should be per listing or per namespace, was never settled; per listing is simpler and makes namespaces compete for the allowance, which may be the wrong incentive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix]

TOML includes date and time values and special floating-point values that have no direct JSON representation, and compact JSON does not define one canonical conversion and serialization for all implementations.

Please define the TOML-to-JSON value mapping and a canonical serialization, restrict extension values to a specified JSON-compatible subset, or record the measurement as unresolved.

Comment on lines +128 to +131
### The schema is part of this RFC, not left open

The rules above are normative, so the companion pull request against `KSAModding/content-index` implements exactly them and has no latitude to permit a free subtree at `extensions`: a table, each direct child a table, each name a valid id, case-insensitive duplicates rejected, and the size rule as measured above.
Without that change the field is rejected at publish time regardless of what this RFC says, the way RFC 0048 depends on [content-index#34](https://github.com/KSAModding/content-index/pull/34).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[must fix] This section conflicts with line 85 and with the current repository state.

A Postponed RFC is non-normative, and there is no companion pull request for extensions in KSAModding/content-index yet, but this paragraph says the rules are normative and that the companion pull request implements them.

Please use conditional wording, such as If this RFC is reopened, a companion pull request must implement these rules, and make the same correction in the pull request body.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rfc an RFC proposal or its tracking issue stage:proposed RFC is ready for review

Projects

Status: Inbox

Development

Successfully merging this pull request may close these issues.

2 participants