@rathnasgala2/schemas 3.10.0 → 3.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/THIRD_PARTY_LICENSES.json +1 -1
  2. package/diagnostics/diagnostic-map.json +30 -0
  3. package/docs/catalogs/app-components.json +71 -1
  4. package/docs/catalogs/app-routes.json +27 -4
  5. package/docs/catalogs/schema-inventory.json +4 -4
  6. package/examples/valid/build-input/rules.json +41 -0
  7. package/examples/valid/content-frontmatter/rules.json +41 -0
  8. package/fixtures/boundary/build-input/rules.json +51 -0
  9. package/fixtures/boundary/content-frontmatter/rules.json +51 -0
  10. package/fixtures/invalid/build-input/GRAPHEME_LENGTH_INVALID/cases.json +22 -0
  11. package/fixtures/invalid/build-input/REQUEST_FIELD_UNKNOWN/cases.json +9 -0
  12. package/fixtures/invalid/build-input/SCHEMA_TYPE_INVALID/cases.json +20 -0
  13. package/fixtures/invalid/content-frontmatter/GRAPHEME_LENGTH_INVALID/cases.json +22 -0
  14. package/fixtures/invalid/content-frontmatter/REQUEST_FIELD_UNKNOWN/cases.json +11 -0
  15. package/fixtures/invalid/content-frontmatter/SCHEMA_TYPE_INVALID/cases.json +20 -0
  16. package/fixtures/manifest.json +234 -4
  17. package/fixtures/unknown-field/build-input/rules.json +15 -0
  18. package/fixtures/unknown-field/content-frontmatter/rules.json +15 -0
  19. package/generated/browser/validator-core.mjs +3 -3
  20. package/generated/typescript/contracts/build-input.d.ts +8 -0
  21. package/generated/typescript/contracts/content-frontmatter.d.ts +8 -0
  22. package/openapi/http-catalog.json +38 -2
  23. package/openapi/openapi.yaml +770 -4
  24. package/package.json +1 -1
  25. package/sbom.cdx.json +23 -23
  26. package/schemas/build-input.schema.json +20 -1
  27. package/schemas/content-frontmatter.schema.json +19 -0
@@ -1048,6 +1048,27 @@ components:
1048
1048
  - detail
1049
1049
  - reversible
1050
1050
  type: object
1051
+ ContactEmail:
1052
+ additionalProperties: false
1053
+ description: The verified GitHub primary email the person agreed to receive account and security notices at. The full address never leaves the server; only a masked form is shown.
1054
+ properties:
1055
+ maskedAddress:
1056
+ description: Masked form such as `a…d@example.com`, never the full address. Null or absent unless `state` is `ON_FILE`.
1057
+ maxLength: 320
1058
+ type:
1059
+ - string
1060
+ - "null"
1061
+ state:
1062
+ enum:
1063
+ - NONE
1064
+ - ON_FILE
1065
+ - WITHDRAWN
1066
+ type: string
1067
+ updatedAt:
1068
+ $ref: "#/components/schemas/PortableProblemRfc3339"
1069
+ required:
1070
+ - state
1071
+ type: object
1051
1072
  ContentChangeAppearanceEntry:
1052
1073
  additionalProperties: false
1053
1074
  description: |
@@ -1060,9 +1081,20 @@ components:
1060
1081
  optional: the author's publication palette, written as
1061
1082
  `gala/appearance.json`'s `tokens`; when absent the file's `tokens`
1062
1083
  are preserved unchanged, and `{}` resets to the theme's own colours.
1084
+ `brandMark` (SCHEMA-3.12.0) is optional: a repository-relative path
1085
+ under `assets/brand/`, written as `gala/appearance.json`'s
1086
+ `brandMark` (the site icon); `null` clears it and an absent member
1087
+ preserves the file's value. The App uploads the image file as an
1088
+ ordinary `assets[]` entry in the same plan.
1063
1089
  properties:
1064
1090
  attribution:
1065
1091
  $ref: "#/components/schemas/PortableAppearanceAttribution"
1092
+ brandMark:
1093
+ oneOf:
1094
+ - allOf:
1095
+ - $ref: "#/components/schemas/PortableAppearanceRepoRelativePath"
1096
+ - pattern: ^assets/brand/
1097
+ - type: "null"
1066
1098
  colorModeDefault:
1067
1099
  $ref: "#/components/schemas/AppearanceColorMode"
1068
1100
  themeId:
@@ -1187,6 +1219,55 @@ components:
1187
1219
  - path
1188
1220
  - action
1189
1221
  type: object
1222
+ ContentChangePublicationProfileEntry:
1223
+ additionalProperties: false
1224
+ description: |
1225
+ SCHEMA-3.12.0: site-level settings inside a batch
1226
+ `content-changes:plan` request, the same lifecycle and capability as
1227
+ `appearance` (a pending change that goes live on Publish). The
1228
+ server loads `gala/publication.json` at `baseRevision`, applies the
1229
+ members that are present, validates the result against
1230
+ `publication.schema.json`, and plans one `PUT` of
1231
+ `gala/publication.json`. An absent member is preserved. `null`
1232
+ resets `description` to the publication title (the file requires a
1233
+ description); `null` clears `defaultImageRef` and `crawlers`.
1234
+ `title`, `defaultLanguage` and `socialLinks` cannot be cleared.
1235
+ `socialLinks` (max 32, the publication file's own limit) replaces
1236
+ the whole list. `canonicalBase` is never client-settable: it changes
1237
+ only through domain attach and detach. A profile that changes nothing is
1238
+ `422 VALIDATION_FAILED` pointed at `/publicationProfile`; member
1239
+ failures point at `/publicationProfile/<member>`.
1240
+ properties:
1241
+ crawlers:
1242
+ oneOf:
1243
+ - $ref: "#/components/schemas/PortablePublicationCrawlers"
1244
+ - type: "null"
1245
+ defaultImageRef:
1246
+ oneOf:
1247
+ - allOf:
1248
+ - $ref: "#/components/schemas/PortablePublicationRepoRelativePath"
1249
+ - pattern: ^assets/brand/
1250
+ - type: "null"
1251
+ defaultLanguage:
1252
+ $ref: "#/components/schemas/PortablePublicationBcp47"
1253
+ description:
1254
+ oneOf:
1255
+ - $ref: "#/components/schemas/PortablePublicationPlainText"
1256
+ x-gala-graphemeLength:
1257
+ maximum: 300
1258
+ minimum: 1
1259
+ - type: "null"
1260
+ socialLinks:
1261
+ items:
1262
+ $ref: "#/components/schemas/PortablePublicationSocialLink"
1263
+ maxItems: 32
1264
+ type: array
1265
+ title:
1266
+ $ref: "#/components/schemas/PortablePublicationPlainText"
1267
+ x-gala-graphemeLength:
1268
+ maximum: 120
1269
+ minimum: 1
1270
+ type: object
1190
1271
  ContentFrontmatter:
1191
1272
  $ref: "#/components/schemas/PortableContentFrontmatterDocument"
1192
1273
  ContentInventoryItem:
@@ -1324,14 +1405,36 @@ components:
1324
1405
  $ref: "#/components/schemas/ContentPublicationAuthorSummary"
1325
1406
  maxItems: 200
1326
1407
  type: array
1408
+ crawlers:
1409
+ $ref: "#/components/schemas/PortablePublicationCrawlers"
1410
+ defaultImageRef:
1411
+ $ref: "#/components/schemas/PortablePublicationRepoRelativePath"
1327
1412
  defaultLanguage:
1328
1413
  $ref: "#/components/schemas/PortablePublicationBcp47"
1414
+ description:
1415
+ $ref: "#/components/schemas/PortablePublicationPlainText"
1416
+ x-gala-graphemeLength:
1417
+ maximum: 500
1418
+ minimum: 1
1419
+ socialLinks:
1420
+ items:
1421
+ $ref: "#/components/schemas/PortablePublicationSocialLink"
1422
+ maxItems: 32
1423
+ type: array
1329
1424
  theme:
1330
1425
  $ref: "#/components/schemas/PortableAppearancePackageRange"
1426
+ title:
1427
+ $ref: "#/components/schemas/PortablePublicationPlainText"
1428
+ x-gala-graphemeLength:
1429
+ maximum: 200
1430
+ minimum: 1
1331
1431
  required:
1332
1432
  - defaultLanguage
1333
1433
  - theme
1334
1434
  - authors
1435
+ - title
1436
+ - description
1437
+ - socialLinks
1335
1438
  type: object
1336
1439
  DefaultBranchUpdateState:
1337
1440
  description: |
@@ -4222,6 +4325,8 @@ components:
4222
4325
  uniqueItems: true
4223
4326
  closure:
4224
4327
  $ref: "#/components/schemas/SessionClosure"
4328
+ contactEmail:
4329
+ $ref: "#/components/schemas/ContactEmail"
4225
4330
  credentialEpoch:
4226
4331
  format: int64
4227
4332
  minimum: 0
@@ -6901,6 +7006,9 @@ components:
6901
7006
  PlatformUser:
6902
7007
  additionalProperties: false
6903
7008
  properties:
7009
+ contactEmailOnFile:
7010
+ description: Whether a contact email the person agreed to is on file. The address itself is never returned.
7011
+ type: boolean
6904
7012
  createdAt:
6905
7013
  $ref: "#/components/schemas/PortableProblemRfc3339"
6906
7014
  displayName:
@@ -6943,6 +7051,7 @@ components:
6943
7051
  - lastSignInAt
6944
7052
  - publicationCount
6945
7053
  - planTiers
7054
+ - contactEmailOnFile
6946
7055
  type: object
6947
7056
  PlatformWebhookEvent:
6948
7057
  additionalProperties: false
@@ -7043,6 +7152,15 @@ components:
7043
7152
  minLength: 3
7044
7153
  pattern: ^(?:@[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?/[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?|[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?)@(?:\S+|\S+ \S+)$
7045
7154
  type: string
7155
+ PortableAppearanceRepoRelativePath:
7156
+ description: NFC UTF-8 repository-relative path using slash separators, with no leading slash, dot segment, NUL, backslash, or percent-decoded traversal.
7157
+ format: gala-repository-relative-path
7158
+ maxLength: 512
7159
+ minLength: 1
7160
+ pattern: ^(?!/)(?!.*\\)(?!.*\u0000).+$
7161
+ type: string
7162
+ x-gala-utf8ByteLength:
7163
+ maximum: 512
7046
7164
  PortableAppearanceSemanticTokens:
7047
7165
  additionalProperties: false
7048
7166
  description: "SCHEMA-3.10.0: the author's publication palette. Each role (accent, canvas, text) is optional; when present it carries both light and dark as opaque lowercase #rrggbb. An absent role uses the theme's default; `{}` selects the theme's default palette entirely."
@@ -7145,6 +7263,26 @@ components:
7145
7263
  - generation
7146
7264
  - approvedAt
7147
7265
  type: object
7266
+ PortableContentFrontmatterContentSeo:
7267
+ additionalProperties: false
7268
+ description: "SCHEMA-3.12.0: optional search overrides for one document. `title` replaces the page title in search results (the site suffix is still appended on non-home pages), `description` replaces the search description, `canonicalUrl` is an absolute HTTPS canonical for syndicated or moved content, and `noindex: true` keeps a listed document out of search engines. Every member is optional; absent members fall back to the document's own title and description."
7269
+ properties:
7270
+ canonicalUrl:
7271
+ $ref: "#/components/schemas/PortableContentFrontmatterUrlHttps"
7272
+ description:
7273
+ $ref: "#/components/schemas/PortableContentFrontmatterPlainText"
7274
+ x-gala-graphemeLength:
7275
+ maximum: 300
7276
+ minimum: 1
7277
+ noindex:
7278
+ type: boolean
7279
+ title:
7280
+ $ref: "#/components/schemas/PortableContentFrontmatterPlainText"
7281
+ x-gala-graphemeLength:
7282
+ maximum: 70
7283
+ minimum: 1
7284
+ required: []
7285
+ type: object
7148
7286
  PortableContentFrontmatterDigest:
7149
7287
  pattern: ^sha256:[0-9a-f]{64}$
7150
7288
  type: string
@@ -7241,6 +7379,8 @@ components:
7241
7379
  pattern: ^2\.0\.0$
7242
7380
  type: string
7243
7381
  x-gala-const: 2.0.0
7382
+ seo:
7383
+ $ref: "#/components/schemas/PortableContentFrontmatterContentSeo"
7244
7384
  series:
7245
7385
  $ref: "#/components/schemas/PortableContentFrontmatterPlainLabel"
7246
7386
  seriesOrder:
@@ -7371,6 +7511,11 @@ components:
7371
7511
  description: Lowercase canonical UUIDv7. Once published, it is immutable; its time ordering conveys neither chronology nor authority.
7372
7512
  pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
7373
7513
  type: string
7514
+ PortableContentFrontmatterUrlHttps:
7515
+ description: Absolute HTTPS URL without embedded credentials.
7516
+ format: uri
7517
+ pattern: ^https://(?![^/?#]*@)
7518
+ type: string
7374
7519
  PortableDeploymentIntentAdapterIdentity:
7375
7520
  additionalProperties: false
7376
7521
  properties:
@@ -12926,6 +13071,84 @@ components:
12926
13071
  x-gala-utf8ByteLength:
12927
13072
  maximum: 255
12928
13073
  minimum: 1
13074
+ PortablePublicationCrawlers:
13075
+ additionalProperties: false
13076
+ properties:
13077
+ ai:
13078
+ enum:
13079
+ - allow
13080
+ - block
13081
+ required:
13082
+ - ai
13083
+ type: object
13084
+ PortablePublicationPlainLabel:
13085
+ description: Normalized Unicode plain text without markup, controls, or bidi overrides.
13086
+ format: gala-plain-label
13087
+ type: string
13088
+ x-gala-graphemeLength:
13089
+ maximum: 80
13090
+ minimum: 1
13091
+ PortablePublicationPlainText:
13092
+ description: NFC Unicode text without disallowed C0/C1 controls or bidi override/isolate controls.
13093
+ format: gala-plain-text
13094
+ type: string
13095
+ PortablePublicationRepoRelativePath:
13096
+ description: NFC UTF-8 repository-relative path using slash separators, with no leading slash, dot segment, NUL, backslash, or percent-decoded traversal.
13097
+ format: gala-repository-relative-path
13098
+ maxLength: 512
13099
+ minLength: 1
13100
+ pattern: ^(?!/)(?!.*\\)(?!.*\u0000).+$
13101
+ type: string
13102
+ x-gala-utf8ByteLength:
13103
+ maximum: 512
13104
+ PortablePublicationSocialLink:
13105
+ additionalProperties: false
13106
+ allOf:
13107
+ - else:
13108
+ properties:
13109
+ uri:
13110
+ $ref: "#/components/schemas/PortablePublicationUrlHttps"
13111
+ if:
13112
+ properties:
13113
+ type:
13114
+ pattern: ^email$
13115
+ type: string
13116
+ x-gala-const: email
13117
+ required:
13118
+ - type
13119
+ then:
13120
+ properties:
13121
+ uri:
13122
+ format: uri
13123
+ pattern: "^mailto:"
13124
+ type: string
13125
+ properties:
13126
+ label:
13127
+ $ref: "#/components/schemas/PortablePublicationPlainLabel"
13128
+ type:
13129
+ enum:
13130
+ - website
13131
+ - email
13132
+ - github
13133
+ - linkedin
13134
+ - mastodon
13135
+ - bluesky
13136
+ - x
13137
+ - youtube
13138
+ - other
13139
+ uri:
13140
+ maxLength: 2048
13141
+ minLength: 1
13142
+ type: string
13143
+ required:
13144
+ - type
13145
+ - uri
13146
+ type: object
13147
+ PortablePublicationUrlHttps:
13148
+ description: Absolute HTTPS URL without embedded credentials.
13149
+ format: uri
13150
+ pattern: ^https://(?![^/?#]*@)
13151
+ type: string
12929
13152
  PostAuthenticationGithubTransactionsRequest:
12930
13153
  additionalProperties: false
12931
13154
  properties:
@@ -13704,13 +13927,15 @@ components:
13704
13927
  Two request shapes, both accepted. The 2.13.0 single-document shape
13705
13928
  (`path`, `contentDigest`, `expectedHead`) plans one document write
13706
13929
  against the exact expected head. The additive batch shape
13707
- (`baseRevision` and at least one of `documents`/`assets`/`appearance`)
13930
+ (`baseRevision` and at least one of `documents`/`assets`/`appearance`/
13931
+ `publicationProfile`)
13708
13932
  plans up to 20 documents and 20 assets -- each `PUT` with its own
13709
13933
  text or bytes and digest, each `DELETE` naming only its path -- and
13710
13934
  optionally one theme selection in one change, against the exact
13711
13935
  expected main-branch head asserted as `baseRevision`. A request
13712
13936
  mixing the two shapes, or a batch request naming none of
13713
- `documents`, `assets` and `appearance`, is `422 VALIDATION_FAILED`.
13937
+ `documents`, `assets`, `appearance` and `publicationProfile`, is
13938
+ `422 VALIDATION_FAILED`.
13714
13939
  `appearance` names a catalog theme and a default colour mode, and
13715
13940
  optionally the footer `attribution` (SCHEMA-3.3.0); the server
13716
13941
  writes `gala/appearance.json` (only `theme`, `colorMode.default` and,
@@ -13720,6 +13945,10 @@ components:
13720
13945
  selection (theme, default colour mode and, when sent, attribution)
13721
13946
  is `422 VALIDATION_FAILED` pointed at `/appearance`. Document paths
13722
13947
  under `gala/` and `gala.lock.json` remain forbidden.
13948
+ `publicationProfile` (SCHEMA-3.12.0) is a further batch member beside
13949
+ `appearance`, counting as one of the named members: it edits
13950
+ `gala/publication.json` through one planned `PUT` (see
13951
+ `ContentChangePublicationProfileEntry`).
13723
13952
  Assets are images only (PNG, JPEG, WebP, GIF, AVIF; SVG is refused):
13724
13953
  at most 20 per change, each at most 5 MiB and together at most
13725
13954
  20 MiB, measured on the decoded bytes -- `assets[].bytesBase64` is
@@ -13752,6 +13981,8 @@ components:
13752
13981
  maxLength: 512
13753
13982
  minLength: 1
13754
13983
  type: string
13984
+ publicationProfile:
13985
+ $ref: "#/components/schemas/ContentChangePublicationProfileEntry"
13755
13986
  required: []
13756
13987
  type: object
13757
13988
  PostOrganizationsByOrganizationIdPublicationsByPublicationIdContentChangesPlanResponse:
@@ -14579,7 +14810,16 @@ components:
14579
14810
  - $ref: "#/components/schemas/PublicationTransfer"
14580
14811
  PostOrganizationsByOrganizationIdPublicationsRequest:
14581
14812
  additionalProperties: false
14813
+ description: |
14814
+ `description` (SCHEMA-3.12.0) is the optional site tagline, written
14815
+ as `gala/publication.json`'s `description`. When absent the server
14816
+ keeps its fallback (the site name).
14582
14817
  properties:
14818
+ description:
14819
+ $ref: "#/components/schemas/PortablePublicationPlainText"
14820
+ x-gala-graphemeLength:
14821
+ maximum: 300
14822
+ minimum: 1
14583
14823
  name:
14584
14824
  maxLength: 80
14585
14825
  minLength: 1
@@ -14869,6 +15109,46 @@ components:
14869
15109
  required:
14870
15110
  - client
14871
15111
  type: object
15112
+ PostPlatformUsersByPersonIdContactRequest:
15113
+ additionalProperties: false
15114
+ properties:
15115
+ body:
15116
+ maxLength: 5000
15117
+ minLength: 1
15118
+ type: string
15119
+ category:
15120
+ enum:
15121
+ - ACCOUNT
15122
+ - SECURITY
15123
+ - SERVICE
15124
+ type: string
15125
+ reason:
15126
+ $ref: "#/components/schemas/PlatformOperatorReasonCode"
15127
+ subject:
15128
+ maxLength: 200
15129
+ minLength: 1
15130
+ type: string
15131
+ required:
15132
+ - category
15133
+ - subject
15134
+ - body
15135
+ - reason
15136
+ type: object
15137
+ PostPlatformUsersByPersonIdContactResponse:
15138
+ additionalProperties: false
15139
+ properties:
15140
+ messageId:
15141
+ format: uuid
15142
+ pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
15143
+ type: string
15144
+ state:
15145
+ enum:
15146
+ - QUEUED
15147
+ type: string
15148
+ required:
15149
+ - messageId
15150
+ - state
15151
+ type: object
14872
15152
  PostPublicCommentsByCommentIdAppealsRequest:
14873
15153
  additionalProperties: false
14874
15154
  properties:
@@ -15119,6 +15399,22 @@ components:
15119
15399
  - state
15120
15400
  - fenceAt
15121
15401
  type: object
15402
+ PostSelfContactEmailGrantResponse:
15403
+ additionalProperties: false
15404
+ properties:
15405
+ contactEmail:
15406
+ $ref: "#/components/schemas/ContactEmail"
15407
+ required:
15408
+ - contactEmail
15409
+ type: object
15410
+ PostSelfContactEmailWithdrawResponse:
15411
+ additionalProperties: false
15412
+ properties:
15413
+ contactEmail:
15414
+ $ref: "#/components/schemas/ContactEmail"
15415
+ required:
15416
+ - contactEmail
15417
+ type: object
15122
15418
  PostSelfExportsByExportIdDownloadResponse:
15123
15419
  additionalProperties: false
15124
15420
  properties:
@@ -15729,10 +16025,19 @@ components:
15729
16025
  (SCHEMA-3.3.0, optional) is the file's footer attribution switch;
15730
16026
  absent means the file has none, which renders as shown. `tokens`
15731
16027
  (SCHEMA-3.10.0, optional) is the file's publication palette as read;
15732
- absent or `{}` means the theme's own colours.
16028
+ absent or `{}` means the theme's own colours. `brandMark`
16029
+ (SCHEMA-3.12.0, optional): the publication's brand mark as currently
16030
+ committed, absent when none.
15733
16031
  properties:
15734
16032
  attribution:
15735
16033
  $ref: "#/components/schemas/PortableAppearanceAttribution"
16034
+ brandMark:
16035
+ description: "SCHEMA-3.12.0: the publication's brand mark as currently committed, absent when none"
16036
+ oneOf:
16037
+ - allOf:
16038
+ - $ref: "#/components/schemas/PortableAppearanceRepoRelativePath"
16039
+ - pattern: ^assets/brand/
16040
+ - type: "null"
15736
16041
  colorModeDefault:
15737
16042
  $ref: "#/components/schemas/AppearanceColorMode"
15738
16043
  themeId:
@@ -30225,7 +30530,10 @@ paths:
30225
30530
  - displayName: Example Author
30226
30531
  id: 018f0000-0000-7000-8000-000000000001
30227
30532
  defaultLanguage: en
30533
+ description: Example tagline
30534
+ socialLinks: []
30228
30535
  theme: "@rathnasgala2/theme-default@^4.0.0"
30536
+ title: Example
30229
30537
  setUp: true
30230
30538
  schema:
30231
30539
  $ref: "#/components/schemas/GetOrganizationsByOrganizationIdPublicationsByPublicationIdContentResponse"
@@ -48601,7 +48909,8 @@ paths:
48601
48909
  value:
48602
48910
  hasMore: false
48603
48911
  items:
48604
- - createdAt: "2026-09-01T12:00:00.000Z"
48912
+ - contactEmailOnFile: true
48913
+ createdAt: "2026-09-01T12:00:00.000Z"
48605
48914
  displayName: Ada Reader
48606
48915
  lastSignInAt: "2026-10-10T11:30:00.000Z"
48607
48916
  login: ada-reader
@@ -48650,6 +48959,140 @@ paths:
48650
48959
  - NONE
48651
48960
  x-gala-success-category: query
48652
48961
  x-gala-tenant-scope: NONE
48962
+ /v2/platform/users/{personId}:contact:
48963
+ post:
48964
+ description: |
48965
+ Operators only, with recent authentication. Queues one message to the
48966
+ person's contact email, which they agreed to at sign-in. The address is
48967
+ never returned; the message carries the fixed Galascribe wrapper and
48968
+ the operator's text. `category` is `ACCOUNT`, `SECURITY` or `SERVICE`.
48969
+ `reason` is a non-sensitive operator reason code recorded in the audit
48970
+ event. `Idempotency-Key` is the queued-message identity. `202` means the
48971
+ message is queued, not delivered. `404 RESOURCE_NOT_FOUND` for an
48972
+ unknown person; `409 CONTACT_EMAIL_ABSENT` when no contact email is on
48973
+ file or it was withdrawn.
48974
+ operationId: postPlatformUsersByPersonIdContact
48975
+ parameters:
48976
+ - $ref: "#/components/parameters/XCorrelationId"
48977
+ - example: 018f0000-0000-7000-8000-000000000001
48978
+ in: path
48979
+ name: personId
48980
+ required: true
48981
+ schema:
48982
+ format: uuid
48983
+ pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
48984
+ type: string
48985
+ - $ref: "#/components/parameters/IdempotencyKey"
48986
+ - $ref: "#/components/parameters/XCsrfToken"
48987
+ requestBody:
48988
+ content:
48989
+ application/json:
48990
+ examples:
48991
+ nominal:
48992
+ summary: Nominal valid request
48993
+ value:
48994
+ body: Your site repository needs attention before we can publish.
48995
+ category: SERVICE
48996
+ reason: OPERATOR_REQUESTED
48997
+ subject: Action needed on your Galascribe site
48998
+ schema:
48999
+ $ref: "#/components/schemas/PostPlatformUsersByPersonIdContactRequest"
49000
+ required: true
49001
+ responses:
49002
+ "202":
49003
+ content:
49004
+ application/json:
49005
+ examples:
49006
+ nominal:
49007
+ summary: Nominal successful response
49008
+ value:
49009
+ messageId: 018f0000-0000-7000-8000-000000000003
49010
+ state: QUEUED
49011
+ schema:
49012
+ $ref: "#/components/schemas/PostPlatformUsersByPersonIdContactResponse"
49013
+ description: contact platform user accepted
49014
+ headers:
49015
+ Cache-Control:
49016
+ $ref: "#/components/headers/CacheControlNoStore"
49017
+ X-Correlation-Id:
49018
+ $ref: "#/components/headers/XCorrelationId"
49019
+ "400":
49020
+ $ref: "#/components/responses/RequestInvalid"
49021
+ "401":
49022
+ $ref: "#/components/responses/PlatformAuthenticationRequired"
49023
+ "403":
49024
+ $ref: "#/components/responses/AuthorizationDenied"
49025
+ "404":
49026
+ $ref: "#/components/responses/ResourceNotFound"
49027
+ "409":
49028
+ content:
49029
+ application/problem+json:
49030
+ examples:
49031
+ COMMAND_REPLAY_CONFLICT:
49032
+ summary: COMMAND_REPLAY_CONFLICT
49033
+ value:
49034
+ code: COMMAND_REPLAY_CONFLICT
49035
+ correlationId: 018f0000-0000-7000-8000-000000000001
49036
+ detail: See the operation contract.
49037
+ errors: []
49038
+ retryable: false
49039
+ schemaId: urn:gala:schema:problem:2.0.0
49040
+ schemaVersion: 2.0.0
49041
+ status: 409
49042
+ title: COMMAND_REPLAY_CONFLICT
49043
+ type: urn:gala:problem:command-replay-conflict
49044
+ CONTACT_EMAIL_ABSENT:
49045
+ summary: CONTACT_EMAIL_ABSENT
49046
+ value:
49047
+ code: CONTACT_EMAIL_ABSENT
49048
+ correlationId: 018f0000-0000-7000-8000-000000000001
49049
+ detail: See the operation contract.
49050
+ errors: []
49051
+ retryable: false
49052
+ schemaId: urn:gala:schema:problem:2.0.0
49053
+ schemaVersion: 2.0.0
49054
+ status: 409
49055
+ title: CONTACT_EMAIL_ABSENT
49056
+ type: urn:gala:problem:contact-email-absent
49057
+ schema:
49058
+ $ref: "#/components/schemas/Problem"
49059
+ description: COMMAND_REPLAY_CONFLICT, CONTACT_EMAIL_ABSENT
49060
+ headers:
49061
+ Cache-Control:
49062
+ $ref: "#/components/headers/CacheControlNoStore"
49063
+ X-Correlation-Id:
49064
+ $ref: "#/components/headers/XCorrelationId"
49065
+ x-gala-problem-codes:
49066
+ - COMMAND_REPLAY_CONFLICT
49067
+ - CONTACT_EMAIL_ABSENT
49068
+ security:
49069
+ - browserSession: []
49070
+ summary: contact platform user
49071
+ tags:
49072
+ - platform
49073
+ x-gala-activation-gate: MVP
49074
+ x-gala-activation-guards:
49075
+ - NONE
49076
+ x-gala-capability-key: platform.users.contact
49077
+ x-gala-concurrency: none
49078
+ x-gala-conditional-capabilities: []
49079
+ x-gala-example-profile: NOMINAL_SUCCESS_AND_EACH_REACHABLE_PROBLEM
49080
+ x-gala-nullability: required-and-nullable-are-explicit
49081
+ x-gala-purpose: contact platform user
49082
+ x-gala-reachable-problems:
49083
+ - AUTHENTICATION_REQUIRED
49084
+ - AUTHORIZATION_DENIED
49085
+ - COMMAND_REPLAY_CONFLICT
49086
+ - CONTACT_EMAIL_ABSENT
49087
+ - REAUTH_REQUIRED
49088
+ - REQUEST_FIELD_UNKNOWN
49089
+ - RESOURCE_NOT_FOUND
49090
+ - VALIDATION_FAILED
49091
+ x-gala-replay-identity: idempotency-key
49092
+ x-gala-state-guards:
49093
+ - NONE
49094
+ x-gala-success-category: async
49095
+ x-gala-tenant-scope: NONE
48653
49096
  /v2/platform/webhook-events:
48654
49097
  get:
48655
49098
  description: |
@@ -51775,6 +52218,329 @@ paths:
51775
52218
  - NONE
51776
52219
  x-gala-success-category: protocol
51777
52220
  x-gala-tenant-scope: NONE
52221
+ /v2/self/contact-email:grant:
52222
+ post:
52223
+ description: |
52224
+ Records the person's agreement to receive account and security notices
52225
+ at their verified GitHub primary email. The server reads the address from
52226
+ GitHub with the stored sign-in token, seals it, and answers with the
52227
+ masked form only; the full address never leaves the server. Needs
52228
+ recent authentication: a stale session gets `401 REAUTH_REQUIRED`.
52229
+ `409 CONTACT_EMAIL_UNAVAILABLE` when GitHub reports no verified primary
52230
+ email (`errors[].code` `NO_VERIFIED_PRIMARY_EMAIL`) or the sign-in did
52231
+ not grant the email scope (`SCOPE_NOT_GRANTED`), both at pointer
52232
+ `/contactEmail`; the person signs in again to grant the scope.
52233
+ operationId: postSelfContactEmailGrant
52234
+ parameters:
52235
+ - $ref: "#/components/parameters/XCorrelationId"
52236
+ - $ref: "#/components/parameters/IdempotencyKey"
52237
+ - $ref: "#/components/parameters/XCsrfToken"
52238
+ responses:
52239
+ "200":
52240
+ content:
52241
+ application/json:
52242
+ examples:
52243
+ nominal:
52244
+ summary: Nominal successful response
52245
+ value:
52246
+ contactEmail:
52247
+ maskedAddress: a…d@example.com
52248
+ state: ON_FILE
52249
+ updatedAt: "2026-10-13T12:00:00.000Z"
52250
+ schema:
52251
+ $ref: "#/components/schemas/PostSelfContactEmailGrantResponse"
52252
+ description: grant contact email succeeded
52253
+ headers:
52254
+ Cache-Control:
52255
+ $ref: "#/components/headers/CacheControlNoStore"
52256
+ X-Correlation-Id:
52257
+ $ref: "#/components/headers/XCorrelationId"
52258
+ "400":
52259
+ content:
52260
+ application/problem+json:
52261
+ examples:
52262
+ VALIDATION_FAILED:
52263
+ summary: VALIDATION_FAILED
52264
+ value:
52265
+ code: VALIDATION_FAILED
52266
+ correlationId: 018f0000-0000-7000-8000-000000000001
52267
+ detail: See the operation contract.
52268
+ errors: []
52269
+ retryable: false
52270
+ schemaId: urn:gala:schema:problem:2.0.0
52271
+ schemaVersion: 2.0.0
52272
+ status: 400
52273
+ title: VALIDATION_FAILED
52274
+ type: urn:gala:problem:validation-failed
52275
+ schema:
52276
+ $ref: "#/components/schemas/Problem"
52277
+ description: VALIDATION_FAILED
52278
+ headers:
52279
+ Cache-Control:
52280
+ $ref: "#/components/headers/CacheControlNoStore"
52281
+ X-Correlation-Id:
52282
+ $ref: "#/components/headers/XCorrelationId"
52283
+ x-gala-problem-codes:
52284
+ - VALIDATION_FAILED
52285
+ "401":
52286
+ content:
52287
+ application/problem+json:
52288
+ examples:
52289
+ AUTHENTICATION_REQUIRED:
52290
+ summary: AUTHENTICATION_REQUIRED
52291
+ value:
52292
+ code: AUTHENTICATION_REQUIRED
52293
+ correlationId: 018f0000-0000-7000-8000-000000000001
52294
+ detail: See the operation contract.
52295
+ errors: []
52296
+ retryable: false
52297
+ schemaId: urn:gala:schema:problem:2.0.0
52298
+ schemaVersion: 2.0.0
52299
+ status: 401
52300
+ title: AUTHENTICATION_REQUIRED
52301
+ type: urn:gala:problem:authentication-required
52302
+ REAUTH_REQUIRED:
52303
+ summary: REAUTH_REQUIRED
52304
+ value:
52305
+ code: REAUTH_REQUIRED
52306
+ correlationId: 018f0000-0000-7000-8000-000000000001
52307
+ detail: See the operation contract.
52308
+ errors: []
52309
+ retryable: false
52310
+ schemaId: urn:gala:schema:problem:2.0.0
52311
+ schemaVersion: 2.0.0
52312
+ status: 401
52313
+ title: REAUTH_REQUIRED
52314
+ type: urn:gala:problem:reauth-required
52315
+ schema:
52316
+ $ref: "#/components/schemas/Problem"
52317
+ description: AUTHENTICATION_REQUIRED, REAUTH_REQUIRED
52318
+ headers:
52319
+ Cache-Control:
52320
+ $ref: "#/components/headers/CacheControlNoStore"
52321
+ X-Correlation-Id:
52322
+ $ref: "#/components/headers/XCorrelationId"
52323
+ x-gala-problem-codes:
52324
+ - AUTHENTICATION_REQUIRED
52325
+ - REAUTH_REQUIRED
52326
+ "409":
52327
+ content:
52328
+ application/problem+json:
52329
+ examples:
52330
+ COMMAND_REPLAY_CONFLICT:
52331
+ summary: COMMAND_REPLAY_CONFLICT
52332
+ value:
52333
+ code: COMMAND_REPLAY_CONFLICT
52334
+ correlationId: 018f0000-0000-7000-8000-000000000001
52335
+ detail: See the operation contract.
52336
+ errors: []
52337
+ retryable: false
52338
+ schemaId: urn:gala:schema:problem:2.0.0
52339
+ schemaVersion: 2.0.0
52340
+ status: 409
52341
+ title: COMMAND_REPLAY_CONFLICT
52342
+ type: urn:gala:problem:command-replay-conflict
52343
+ CONTACT_EMAIL_UNAVAILABLE:
52344
+ summary: CONTACT_EMAIL_UNAVAILABLE
52345
+ value:
52346
+ code: CONTACT_EMAIL_UNAVAILABLE
52347
+ correlationId: 018f0000-0000-7000-8000-000000000001
52348
+ detail: See the operation contract.
52349
+ errors:
52350
+ - code: NO_VERIFIED_PRIMARY_EMAIL
52351
+ pointer: /contactEmail
52352
+ retryable: false
52353
+ schemaId: urn:gala:schema:problem:2.0.0
52354
+ schemaVersion: 2.0.0
52355
+ status: 409
52356
+ title: CONTACT_EMAIL_UNAVAILABLE
52357
+ type: urn:gala:problem:contact-email-unavailable
52358
+ schema:
52359
+ $ref: "#/components/schemas/Problem"
52360
+ description: COMMAND_REPLAY_CONFLICT, CONTACT_EMAIL_UNAVAILABLE
52361
+ headers:
52362
+ Cache-Control:
52363
+ $ref: "#/components/headers/CacheControlNoStore"
52364
+ X-Correlation-Id:
52365
+ $ref: "#/components/headers/XCorrelationId"
52366
+ x-gala-problem-codes:
52367
+ - COMMAND_REPLAY_CONFLICT
52368
+ - CONTACT_EMAIL_UNAVAILABLE
52369
+ security:
52370
+ - browserSession: []
52371
+ summary: grant contact email
52372
+ tags:
52373
+ - self
52374
+ x-gala-activation-gate: MVP
52375
+ x-gala-activation-guards:
52376
+ - NONE
52377
+ x-gala-capability-key: null
52378
+ x-gala-concurrency: principal-epoch
52379
+ x-gala-conditional-capabilities: []
52380
+ x-gala-example-profile: NOMINAL_SUCCESS_AND_EACH_REACHABLE_PROBLEM
52381
+ x-gala-nullability: required-and-nullable-are-explicit
52382
+ x-gala-purpose: grant contact email
52383
+ x-gala-reachable-problems:
52384
+ - AUTHENTICATION_REQUIRED
52385
+ - COMMAND_REPLAY_CONFLICT
52386
+ - CONTACT_EMAIL_UNAVAILABLE
52387
+ - REAUTH_REQUIRED
52388
+ - VALIDATION_FAILED
52389
+ x-gala-replay-identity: idempotency-key
52390
+ x-gala-state-guards:
52391
+ - NONE
52392
+ x-gala-success-category: protocol
52393
+ x-gala-tenant-scope: NONE
52394
+ /v2/self/contact-email:withdraw:
52395
+ post:
52396
+ description: |
52397
+ Withdraws the agreement to receive notices by email. The sealed address
52398
+ is deleted, the state reads `WITHDRAWN`, and the person is not asked
52399
+ again. Safe to repeat. Needs recent authentication: a stale session
52400
+ gets `401 REAUTH_REQUIRED`.
52401
+ operationId: postSelfContactEmailWithdraw
52402
+ parameters:
52403
+ - $ref: "#/components/parameters/XCorrelationId"
52404
+ - $ref: "#/components/parameters/IdempotencyKey"
52405
+ - $ref: "#/components/parameters/XCsrfToken"
52406
+ responses:
52407
+ "200":
52408
+ content:
52409
+ application/json:
52410
+ examples:
52411
+ nominal:
52412
+ summary: Nominal successful response
52413
+ value:
52414
+ contactEmail:
52415
+ state: WITHDRAWN
52416
+ updatedAt: "2026-10-13T12:00:00.000Z"
52417
+ schema:
52418
+ $ref: "#/components/schemas/PostSelfContactEmailWithdrawResponse"
52419
+ description: withdraw contact email succeeded
52420
+ headers:
52421
+ Cache-Control:
52422
+ $ref: "#/components/headers/CacheControlNoStore"
52423
+ X-Correlation-Id:
52424
+ $ref: "#/components/headers/XCorrelationId"
52425
+ "400":
52426
+ content:
52427
+ application/problem+json:
52428
+ examples:
52429
+ VALIDATION_FAILED:
52430
+ summary: VALIDATION_FAILED
52431
+ value:
52432
+ code: VALIDATION_FAILED
52433
+ correlationId: 018f0000-0000-7000-8000-000000000001
52434
+ detail: See the operation contract.
52435
+ errors: []
52436
+ retryable: false
52437
+ schemaId: urn:gala:schema:problem:2.0.0
52438
+ schemaVersion: 2.0.0
52439
+ status: 400
52440
+ title: VALIDATION_FAILED
52441
+ type: urn:gala:problem:validation-failed
52442
+ schema:
52443
+ $ref: "#/components/schemas/Problem"
52444
+ description: VALIDATION_FAILED
52445
+ headers:
52446
+ Cache-Control:
52447
+ $ref: "#/components/headers/CacheControlNoStore"
52448
+ X-Correlation-Id:
52449
+ $ref: "#/components/headers/XCorrelationId"
52450
+ x-gala-problem-codes:
52451
+ - VALIDATION_FAILED
52452
+ "401":
52453
+ content:
52454
+ application/problem+json:
52455
+ examples:
52456
+ AUTHENTICATION_REQUIRED:
52457
+ summary: AUTHENTICATION_REQUIRED
52458
+ value:
52459
+ code: AUTHENTICATION_REQUIRED
52460
+ correlationId: 018f0000-0000-7000-8000-000000000001
52461
+ detail: See the operation contract.
52462
+ errors: []
52463
+ retryable: false
52464
+ schemaId: urn:gala:schema:problem:2.0.0
52465
+ schemaVersion: 2.0.0
52466
+ status: 401
52467
+ title: AUTHENTICATION_REQUIRED
52468
+ type: urn:gala:problem:authentication-required
52469
+ REAUTH_REQUIRED:
52470
+ summary: REAUTH_REQUIRED
52471
+ value:
52472
+ code: REAUTH_REQUIRED
52473
+ correlationId: 018f0000-0000-7000-8000-000000000001
52474
+ detail: See the operation contract.
52475
+ errors: []
52476
+ retryable: false
52477
+ schemaId: urn:gala:schema:problem:2.0.0
52478
+ schemaVersion: 2.0.0
52479
+ status: 401
52480
+ title: REAUTH_REQUIRED
52481
+ type: urn:gala:problem:reauth-required
52482
+ schema:
52483
+ $ref: "#/components/schemas/Problem"
52484
+ description: AUTHENTICATION_REQUIRED, REAUTH_REQUIRED
52485
+ headers:
52486
+ Cache-Control:
52487
+ $ref: "#/components/headers/CacheControlNoStore"
52488
+ X-Correlation-Id:
52489
+ $ref: "#/components/headers/XCorrelationId"
52490
+ x-gala-problem-codes:
52491
+ - AUTHENTICATION_REQUIRED
52492
+ - REAUTH_REQUIRED
52493
+ "409":
52494
+ content:
52495
+ application/problem+json:
52496
+ examples:
52497
+ COMMAND_REPLAY_CONFLICT:
52498
+ summary: COMMAND_REPLAY_CONFLICT
52499
+ value:
52500
+ code: COMMAND_REPLAY_CONFLICT
52501
+ correlationId: 018f0000-0000-7000-8000-000000000001
52502
+ detail: See the operation contract.
52503
+ errors: []
52504
+ retryable: false
52505
+ schemaId: urn:gala:schema:problem:2.0.0
52506
+ schemaVersion: 2.0.0
52507
+ status: 409
52508
+ title: COMMAND_REPLAY_CONFLICT
52509
+ type: urn:gala:problem:command-replay-conflict
52510
+ schema:
52511
+ $ref: "#/components/schemas/Problem"
52512
+ description: COMMAND_REPLAY_CONFLICT
52513
+ headers:
52514
+ Cache-Control:
52515
+ $ref: "#/components/headers/CacheControlNoStore"
52516
+ X-Correlation-Id:
52517
+ $ref: "#/components/headers/XCorrelationId"
52518
+ x-gala-problem-codes:
52519
+ - COMMAND_REPLAY_CONFLICT
52520
+ security:
52521
+ - browserSession: []
52522
+ summary: withdraw contact email
52523
+ tags:
52524
+ - self
52525
+ x-gala-activation-gate: MVP
52526
+ x-gala-activation-guards:
52527
+ - NONE
52528
+ x-gala-capability-key: null
52529
+ x-gala-concurrency: principal-epoch
52530
+ x-gala-conditional-capabilities: []
52531
+ x-gala-example-profile: NOMINAL_SUCCESS_AND_EACH_REACHABLE_PROBLEM
52532
+ x-gala-nullability: required-and-nullable-are-explicit
52533
+ x-gala-purpose: withdraw contact email
52534
+ x-gala-reachable-problems:
52535
+ - AUTHENTICATION_REQUIRED
52536
+ - COMMAND_REPLAY_CONFLICT
52537
+ - REAUTH_REQUIRED
52538
+ - VALIDATION_FAILED
52539
+ x-gala-replay-identity: idempotency-key
52540
+ x-gala-state-guards:
52541
+ - NONE
52542
+ x-gala-success-category: protocol
52543
+ x-gala-tenant-scope: NONE
51778
52544
  /v2/self/exports:
51779
52545
  get:
51780
52546
  description: |