commit dc5af7eebfd05cca4acca313c4c544f4cace59f6
parent 226ed50e0d94e069d4f53c2ef6b59fe25e916408
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 4 Aug 2026 18:41:14 +0200
enable use of '=' in slugs, we need it for the session_id
Diffstat:
4 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/core/api-common.rst b/core/api-common.rst
@@ -291,16 +291,23 @@ without any escaping. We call such an identifier a *slug*.
.. ts:def:: Slug
// Non-empty string that can be used as-is as a single path
- // component of a URL. Thus, a slug must not contain a "/"
- // and must only use characters that RFC 3986 allows in a path
- // segment without percent-encoding, that is unreserved
- // characters ("A-Z", "a-z", "0-9", "-", ".", "_", "~"),
- // sub-delimiters ("!$&'()*+,;=") and ":" and "@".
+ // component of a URL. A slug must only use ASCII alphanumeric
+ // characters ("A-Z", "a-z", "0-9") and the five punctuation
+ // characters "-", ".", "_", ":" and "=". Consequently a slug
+ // never contains a "/" and never requires percent-encoding.
+ // The strings "." and ".." are not valid slugs, as they have a
+ // special meaning in URL paths.
// Slugs are case-sensitive. Individual endpoints may impose
// additional restrictions on the slugs they accept; those are
// documented with the respective endpoint or field.
type Slug = string;
+This character set is deliberately narrower than what RFC 3986 permits in a
+path segment: it excludes ``@``, ``~`` and all sub-delimiters except ``=``,
+which are legal in a URL path but cause trouble once a slug is embedded in
+other syntax, such as a shell command, a query string or a filename. ``=`` is
+permitted because base64-encoded identifiers may end in padding.
+
Note that a slug is *not* the same as an opaque identifier that merely happens
to be a string: identifiers that may contain arbitrary characters (and thus
require percent-encoding when put into a URL) are documented as plain
diff --git a/core/merchant/get-private-tokenfamilies-TOKEN_FAMILY_SLUG.rst b/core/merchant/get-private-tokenfamilies-TOKEN_FAMILY_SLUG.rst
@@ -28,8 +28,7 @@
interface TokenFamilyDetails {
- // Identifier for the token family consisting of unreserved characters
- // according to RFC 3986.
+ // Identifier for the token family.
slug: Slug;
// Human-readable name for the token family.
diff --git a/core/merchant/get-private-tokenfamilies.rst b/core/merchant/get-private-tokenfamilies.rst
@@ -32,8 +32,7 @@
.. ts:def:: TokenFamilySummary
interface TokenFamilySummary {
- // Identifier for the token family consisting of unreserved characters
- // according to RFC 3986.
+ // Identifier for the token family.
slug: Slug;
// Human-readable name for the token family.
diff --git a/core/merchant/post-private-tokenfamilies.rst b/core/merchant/post-private-tokenfamilies.rst
@@ -40,8 +40,7 @@
interface TokenFamilyCreateRequest {
- // Identifier for the token family consisting of unreserved characters
- // according to RFC 3986.
+ // Identifier for the token family.
slug: Slug;
// Human-readable name for the token family.