@remit/api-openapi-spec 0.0.41 → 0.0.43
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.
- package/openapi.json +347 -23
- package/package.json +1 -1
package/openapi.json
CHANGED
|
@@ -2323,6 +2323,133 @@
|
|
|
2323
2323
|
}
|
|
2324
2324
|
}
|
|
2325
2325
|
},
|
|
2326
|
+
"/calendars/{calendarId}/feed": {
|
|
2327
|
+
"get": {
|
|
2328
|
+
"operationId": "CalendarDetailOperations_getCalendarFeed",
|
|
2329
|
+
"description": "Read whether this calendar has a feed address. Absent (404) until one is\nminted. The token is not here: it is stored as a hash, so the only\nmoment it exists in the clear is the answer to the write below.",
|
|
2330
|
+
"parameters": [
|
|
2331
|
+
{
|
|
2332
|
+
"name": "calendarId",
|
|
2333
|
+
"in": "path",
|
|
2334
|
+
"required": true,
|
|
2335
|
+
"schema": {
|
|
2336
|
+
"$ref": "#/components/schemas/UUID"
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
],
|
|
2340
|
+
"responses": {
|
|
2341
|
+
"200": {
|
|
2342
|
+
"description": "The request has succeeded.",
|
|
2343
|
+
"content": {
|
|
2344
|
+
"application/json": {
|
|
2345
|
+
"schema": {
|
|
2346
|
+
"$ref": "#/components/schemas/RemitImap.CalendarFeedStateResponse"
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
},
|
|
2351
|
+
"404": {
|
|
2352
|
+
"description": "Not found error response",
|
|
2353
|
+
"content": {
|
|
2354
|
+
"application/json": {
|
|
2355
|
+
"schema": {
|
|
2356
|
+
"$ref": "#/components/schemas/ApiError"
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
},
|
|
2362
|
+
"x-amazon-apigateway-integration": {
|
|
2363
|
+
"type": "aws_proxy",
|
|
2364
|
+
"httpMethod": "POST",
|
|
2365
|
+
"passthroughBehavior": "when_no_match",
|
|
2366
|
+
"uri": {
|
|
2367
|
+
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:{{HandlerFunctionName}}/invocations"
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
},
|
|
2371
|
+
"put": {
|
|
2372
|
+
"operationId": "CalendarDetailOperations_putCalendarFeed",
|
|
2373
|
+
"description": "Mint the calendar's feed address, or replace the one it has, and answer\nwith the token in the clear. Idempotent in address rather than in value:\none calendar holds one token, so a second call rotates — the previous\nURL stops resolving, which is how a subscription handed to the wrong\nperson is taken back.\n\nThis is the only response that ever carries the plaintext. A client that\ndoes not keep it rotates again.",
|
|
2374
|
+
"parameters": [
|
|
2375
|
+
{
|
|
2376
|
+
"name": "calendarId",
|
|
2377
|
+
"in": "path",
|
|
2378
|
+
"required": true,
|
|
2379
|
+
"schema": {
|
|
2380
|
+
"$ref": "#/components/schemas/UUID"
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
],
|
|
2384
|
+
"responses": {
|
|
2385
|
+
"200": {
|
|
2386
|
+
"description": "The request has succeeded.",
|
|
2387
|
+
"content": {
|
|
2388
|
+
"application/json": {
|
|
2389
|
+
"schema": {
|
|
2390
|
+
"$ref": "#/components/schemas/RemitImap.CalendarFeedResponse"
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
},
|
|
2395
|
+
"404": {
|
|
2396
|
+
"description": "Not found error response",
|
|
2397
|
+
"content": {
|
|
2398
|
+
"application/json": {
|
|
2399
|
+
"schema": {
|
|
2400
|
+
"$ref": "#/components/schemas/ApiError"
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
},
|
|
2406
|
+
"x-amazon-apigateway-integration": {
|
|
2407
|
+
"type": "aws_proxy",
|
|
2408
|
+
"httpMethod": "POST",
|
|
2409
|
+
"passthroughBehavior": "when_no_match",
|
|
2410
|
+
"uri": {
|
|
2411
|
+
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:{{HandlerFunctionName}}/invocations"
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
},
|
|
2415
|
+
"delete": {
|
|
2416
|
+
"operationId": "CalendarDetailOperations_revokeCalendarFeed",
|
|
2417
|
+
"description": "Revoke the calendar's feed address. Every subscribed client starts getting 404 on its next poll. Answered 404 when the calendar has no feed, so a revoke is never reported as having taken something away that was not there.",
|
|
2418
|
+
"parameters": [
|
|
2419
|
+
{
|
|
2420
|
+
"name": "calendarId",
|
|
2421
|
+
"in": "path",
|
|
2422
|
+
"required": true,
|
|
2423
|
+
"schema": {
|
|
2424
|
+
"$ref": "#/components/schemas/UUID"
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
],
|
|
2428
|
+
"responses": {
|
|
2429
|
+
"204": {
|
|
2430
|
+
"description": "Nothing to return. The resource, or the occurrence, is gone."
|
|
2431
|
+
},
|
|
2432
|
+
"404": {
|
|
2433
|
+
"description": "Not found error response",
|
|
2434
|
+
"content": {
|
|
2435
|
+
"application/json": {
|
|
2436
|
+
"schema": {
|
|
2437
|
+
"$ref": "#/components/schemas/ApiError"
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
},
|
|
2443
|
+
"x-amazon-apigateway-integration": {
|
|
2444
|
+
"type": "aws_proxy",
|
|
2445
|
+
"httpMethod": "POST",
|
|
2446
|
+
"passthroughBehavior": "when_no_match",
|
|
2447
|
+
"uri": {
|
|
2448
|
+
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:{{HandlerFunctionName}}/invocations"
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
},
|
|
2326
2453
|
"/config": {
|
|
2327
2454
|
"get": {
|
|
2328
2455
|
"operationId": "ConfigOperations_getConfig",
|
|
@@ -2434,6 +2561,107 @@
|
|
|
2434
2561
|
}
|
|
2435
2562
|
}
|
|
2436
2563
|
},
|
|
2564
|
+
"/feeds/calendar/{feedToken}.ics": {
|
|
2565
|
+
"get": {
|
|
2566
|
+
"operationId": "CalendarFeedOperations_getCalendarFeedIcal",
|
|
2567
|
+
"description": "Serve a calendar as iCalendar text to whoever holds its secret address\n(issue #1067).\n\nOutside the session-auth surface on purpose: Apple Calendar, Google\nCalendar, Outlook and Thunderbird subscribe to a URL and never sign in,\nso the token in the path is the credential and the only one. It is\ncompared against the stored hash rather than looked up in the clear, and\nan unknown, revoked or malformed token is the same 404 with the same body\n— a subscriber learns whether it still has access, and nothing else.",
|
|
2568
|
+
"parameters": [
|
|
2569
|
+
{
|
|
2570
|
+
"name": "feedToken",
|
|
2571
|
+
"in": "path",
|
|
2572
|
+
"required": true,
|
|
2573
|
+
"description": "The calendar's secret token, base64url. Unconstrained on purpose: a length or pattern here answers an oversize or malformed address with a distinguishable 400, and error-logs the path it was refused for. The handler checks the shape itself and answers the same 404 an unknown token gets.",
|
|
2574
|
+
"schema": {
|
|
2575
|
+
"type": "string"
|
|
2576
|
+
}
|
|
2577
|
+
},
|
|
2578
|
+
{
|
|
2579
|
+
"name": "If-None-Match",
|
|
2580
|
+
"in": "header",
|
|
2581
|
+
"required": false,
|
|
2582
|
+
"schema": {
|
|
2583
|
+
"type": "string"
|
|
2584
|
+
}
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
"name": "If-Modified-Since",
|
|
2588
|
+
"in": "header",
|
|
2589
|
+
"required": false,
|
|
2590
|
+
"description": "HTTP-date a subscriber last saw the calendar at. Ignored when `If-None-Match` also arrives (RFC 9110 13.2.2), and compared at whole seconds, which is the resolution the `Last-Modified` it came from has.",
|
|
2591
|
+
"schema": {
|
|
2592
|
+
"type": "string"
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
],
|
|
2596
|
+
"responses": {
|
|
2597
|
+
"200": {
|
|
2598
|
+
"description": "A whole calendar as iCalendar text, for a client that subscribed to the\nsecret address.\n\nRecurring events are the stored masters with their RRULE, not an expansion:\na subscriber renders its own occurrences and expects to keep doing so\nindefinitely, and an expansion would silently end at whatever horizon this\nserver chose.\n\nThe calendar's name travels as the `X-WR-CALNAME` property inside the\nVCALENDAR, which is where Apple Calendar, Google Calendar and Thunderbird\nread it from.",
|
|
2599
|
+
"headers": {
|
|
2600
|
+
"ETag": {
|
|
2601
|
+
"required": true,
|
|
2602
|
+
"description": "Strong entity tag over the bytes being served. A subscriber polls often and sends it back as `If-None-Match`.",
|
|
2603
|
+
"schema": {
|
|
2604
|
+
"type": "string"
|
|
2605
|
+
}
|
|
2606
|
+
},
|
|
2607
|
+
"Last-Modified": {
|
|
2608
|
+
"required": true,
|
|
2609
|
+
"description": "HTTP-date the collection was last written, which is stamped by every event write and every event delete. The collection's own timestamp rather than its newest event: deleting the newest event leaves every survivor older than the change, and a validator that moved backwards would tell a subscriber its stale copy is current.",
|
|
2610
|
+
"schema": {
|
|
2611
|
+
"type": "string"
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
},
|
|
2615
|
+
"content": {
|
|
2616
|
+
"text/calendar; charset=utf-8": {
|
|
2617
|
+
"schema": {
|
|
2618
|
+
"type": "string"
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
},
|
|
2623
|
+
"304": {
|
|
2624
|
+
"description": "The subscriber already holds these bytes. Answered when `If-None-Match` carries the tag the feed would serve, or when `If-Modified-Since` is not older than the calendar's last change.",
|
|
2625
|
+
"headers": {
|
|
2626
|
+
"ETag": {
|
|
2627
|
+
"required": true,
|
|
2628
|
+
"schema": {
|
|
2629
|
+
"type": "string"
|
|
2630
|
+
}
|
|
2631
|
+
},
|
|
2632
|
+
"Last-Modified": {
|
|
2633
|
+
"required": true,
|
|
2634
|
+
"description": "The same validator a 200 would have carried, so a subscriber that polls by date can keep doing so",
|
|
2635
|
+
"schema": {
|
|
2636
|
+
"type": "string"
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
},
|
|
2641
|
+
"404": {
|
|
2642
|
+
"description": "No feed answers to this address. Unknown, revoked and malformed tokens are one answer with one body, so a caller learns nothing about which of the three it sent.",
|
|
2643
|
+
"content": {
|
|
2644
|
+
"text/plain; charset=utf-8": {
|
|
2645
|
+
"schema": {
|
|
2646
|
+
"type": "string"
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
},
|
|
2652
|
+
"security": [
|
|
2653
|
+
{}
|
|
2654
|
+
],
|
|
2655
|
+
"x-amazon-apigateway-integration": {
|
|
2656
|
+
"type": "aws_proxy",
|
|
2657
|
+
"httpMethod": "POST",
|
|
2658
|
+
"passthroughBehavior": "when_no_match",
|
|
2659
|
+
"uri": {
|
|
2660
|
+
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:{{HandlerFunctionName}}/invocations"
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
},
|
|
2437
2665
|
"/mailboxes/{mailboxId}/threads": {
|
|
2438
2666
|
"get": {
|
|
2439
2667
|
"operationId": "ThreadOperations_listThreads",
|
|
@@ -3863,7 +4091,7 @@
|
|
|
3863
4091
|
"/threads": {
|
|
3864
4092
|
"get": {
|
|
3865
4093
|
"operationId": "UnifiedThreadOperations_listAllThreads",
|
|
3866
|
-
"description": "List threads across all non-muted accounts of the caller, ordered by sentDate desc. Each row carries an attached `accountId` (derived from a mailboxId→accountId map at read time) plus the usual `senderTrust` enrichment; `category` is served from the ThreadMessage row. Served by the `byDate` LSI1 (pk = the caller's account config), so the caller can never see another account config's threads.\n\nINBOX scope: results are filtered to each account's top-level INBOX, matched by exact path `fullPath === \"INBOX\"` (RFC 6154 defines no Inbox special-use). By design this excludes namespaced sub-paths like `INBOX/Receipts` and non-English server primaries — the unified inbox is each account's primary INBOX, not its sub-folders. Soft-deleted rows are also excluded.\n\nMute exclusion: muted accounts and muted mailboxes are excluded. The inbox/mute filter set is rebuilt per page from live state, so muting/unmuting a mailbox mid-pagination takes effect on the next page (never retroactively).\n\nPagination: pass the returned `continuationToken` to fetch the next page; keep paging until it is absent. In the default (INBOX) mode the INBOX/deleted filter is applied after the index read with a bounded read window per request, so a page may return FEWER than `limit` rows while still carrying a `continuationToken` — treat the presence of the token (not a full page) as the \"more results\" signal. No rows are skipped or duplicated across pages.\n\nStarred mode (`starred=true`): served by the `byStarred` LSI4 instead. A star is a marker on the mail rather than on its placement, so the INBOX scope does not apply and a starred thread in Archive is still returned. Excluded are muted and soft-deleted rows as usual, plus the folders a star never surfaces from: Junk, Trash, and Gmail's All Mail (a second copy of everything, whose rows would otherwise double every starred message). All filtering happens in the query, so a page is short only when the results are exhausted. Rows are per mailbox: the same mail filed in two folders is two rows sharing a `threadId`, and a client rendering one row per conversation collapses by `threadId` across the pages it has accumulated.\n\nSearch mode (`query=<text>`): the listing widens past the INBOX scope to every non-muted mailbox of every non-muted account, and returns only rows whose subject or From address matches the text. This is the unscoped search of the daily brief: one query reaching every folder of every account. Whitespace splits the text into terms and every term must match (AND), each against subject OR From. Matching is case-insensitive substring, not tokenized full-text, so it neither stems nor ranks.\n\nSearch scope: every non-muted mailbox EXCEPT Trash. The scope is defined by what it excludes, so anything a server offers that is not on that list is searched — Spam, Drafts and Gmail's virtual folders (All Mail, Starred, Important) included. Spam is deliberately in scope: the point of an unscoped search is that it reaches the folders the user did not think to look in. Combining `query` with `starred=true` searches the starred scope instead.\n\nDuplicates: a virtual folder holds a second copy of mail that also lives in a real folder, so a backend keying a row by its mailbox returns the same message several times — a starred, Important Gmail inbox message four times. The extras are dropped from the response by message identity, keeping the copy in a real folder, so one message is one row. This is done after the read rather than by barring those folders from the scope, because a message whose only stored row sits in one of them would otherwise become unfindable. De-duplication is per page: a duplicate split across a page boundary survives, the same caveat that applies to collapsing by `threadId`. A page may therefore return fewer rows than `limit` while still carrying a `continuationToken`.\n\nSearch mode and pagination: `limit` is a page size over MATCHES, capped server-side at 500. A page may be shorter than `limit` for two reasons — the matches ran out, or duplicates were dropped from it — so treat the presence of a `continuationToken` as the \"more results\" signal rather than a full page. There is no total match count; page until the token is absent.\n\nWhat a row is in search mode: one per message, not one per mailbox. This differs from the starred mode above, where the same mail filed in two folders is two rows sharing a `threadId`. Collapsing by `threadId` is still a client's job if it renders one row per CONVERSATION, since distinct messages in one thread remain distinct rows here.\n\nCallers that omit `query` are unaffected: the INBOX (and starred) listings behave exactly as before.",
|
|
4094
|
+
"description": "List threads across all non-muted accounts of the caller, ordered by sentDate desc. Each row carries an attached `accountId` (derived from a mailboxId→accountId map at read time) plus the usual `senderTrust` enrichment; `category` is served from the ThreadMessage row. Served by the `byDate` LSI1 (pk = the caller's account config), so the caller can never see another account config's threads.\n\nINBOX scope: results are filtered to each account's top-level INBOX, matched by exact path `fullPath === \"INBOX\"` (RFC 6154 defines no Inbox special-use). By design this excludes namespaced sub-paths like `INBOX/Receipts` and non-English server primaries — the unified inbox is each account's primary INBOX, not its sub-folders. Soft-deleted rows are also excluded.\n\nMute exclusion: muted accounts and muted mailboxes are excluded. The inbox/mute filter set is rebuilt per page from live state, so muting/unmuting a mailbox mid-pagination takes effect on the next page (never retroactively).\n\nPagination: pass the returned `continuationToken` to fetch the next page; keep paging until it is absent. In the default (INBOX) mode the INBOX/deleted filter is applied after the index read with a bounded read window per request, so a page may return FEWER than `limit` rows while still carrying a `continuationToken` — treat the presence of the token (not a full page) as the \"more results\" signal. No rows are skipped or duplicated across pages.\n\nStarred mode (`starred=true`): served by the `byStarred` LSI4 instead. A star is a marker on the mail rather than on its placement, so the INBOX scope does not apply and a starred thread in Archive is still returned. Excluded are muted and soft-deleted rows as usual, plus the folders a star never surfaces from: Junk, Trash, and Gmail's All Mail (a second copy of everything, whose rows would otherwise double every starred message). All filtering happens in the query, so a page is short only when the results are exhausted. Rows are per mailbox: the same mail filed in two folders is two rows sharing a `threadId`, and a client rendering one row per conversation collapses by `threadId` across the pages it has accumulated.\n\nSearch mode (`query=<text>`): the listing widens past the INBOX scope to every non-muted mailbox of every non-muted account, and returns only rows whose subject or From address matches the text. This is the unscoped search of the daily brief: one query reaching every folder of every account. Whitespace splits the text into terms and every term must match (AND), each against subject OR From. Matching is case-insensitive substring, not tokenized full-text, so it neither stems nor ranks.\n\nSearch scope: every non-muted mailbox EXCEPT Trash. The scope is defined by what it excludes, so anything a server offers that is not on that list is searched — Spam, Drafts and Gmail's virtual folders (All Mail, Starred, Important) included. Spam is deliberately in scope: the point of an unscoped search is that it reaches the folders the user did not think to look in. Combining `query` with `starred=true` searches the starred scope instead.\n\nDuplicates: a virtual folder holds a second copy of mail that also lives in a real folder, so a backend keying a row by its mailbox returns the same message several times — a starred, Important Gmail inbox message four times. The extras are dropped from the response by message identity, keeping the copy in a real folder, so one message is one row. This is done after the read rather than by barring those folders from the scope, because a message whose only stored row sits in one of them would otherwise become unfindable. De-duplication is per page: a duplicate split across a page boundary survives, the same caveat that applies to collapsing by `threadId`. A page may therefore return fewer rows than `limit` while still carrying a `continuationToken`.\n\nSearch mode and pagination: `limit` is a page size over MATCHES, capped server-side at 500. A page may be shorter than `limit` for two reasons — the matches ran out, or duplicates were dropped from it — so treat the presence of a `continuationToken` as the \"more results\" signal rather than a full page. There is no total match count; page until the token is absent.\n\nWhat a row is in search mode: one per message, not one per mailbox. This differs from the starred mode above, where the same mail filed in two folders is two rows sharing a `threadId`. Collapsing by `threadId` is still a client's job if it renders one row per CONVERSATION, since distinct messages in one thread remain distinct rows here.\n\nCallers that omit `query` are unaffected: the INBOX (and starred) listings behave exactly as before.\n\nRow filters: `category`, `unread` and `attachments` are columns on the ThreadMessage row, so each is a predicate inside the query rather than a pass over what a page returned. They compose with every mode above — INBOX, starred and search alike — and a page therefore comes back full of matches however rare the criterion is. This is what the cross-account collections need: filtering the pages a client happens to have loaded shows an empty list whenever the matching mail sits below the newest page (#308).\n\nCounting: `count=true` answers how many CONVERSATIONS match, over the whole scope and independent of `limit`. `results=false` omits the rows, which is how a header total is read without also paying for a page of mail. Conversations rather than rows because that is what this listing renders: a row is per mailbox, so the same mail filed in two folders is two rows sharing a `threadId`, and clients collapse by it. Counting rows would put a third number beside a list that shows a second one.",
|
|
3867
4095
|
"parameters": [
|
|
3868
4096
|
{
|
|
3869
4097
|
"name": "continuationToken",
|
|
@@ -3907,6 +4135,54 @@
|
|
|
3907
4135
|
"schema": {
|
|
3908
4136
|
"type": "string"
|
|
3909
4137
|
}
|
|
4138
|
+
},
|
|
4139
|
+
{
|
|
4140
|
+
"name": "category",
|
|
4141
|
+
"in": "query",
|
|
4142
|
+
"required": false,
|
|
4143
|
+
"description": "Filter to messages with one of these header-derived categories, as a union over the values given. Applied as a SQL predicate over the whole scope, so a page comes back full of matches however rare the category is. `uncategorized` is one of them — the pending state's name, never the absence of one.",
|
|
4144
|
+
"schema": {
|
|
4145
|
+
"type": "array",
|
|
4146
|
+
"items": {
|
|
4147
|
+
"$ref": "#/components/schemas/RemitImap.MessageCategory"
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
},
|
|
4151
|
+
{
|
|
4152
|
+
"name": "unread",
|
|
4153
|
+
"in": "query",
|
|
4154
|
+
"required": false,
|
|
4155
|
+
"description": "When true, return only unread messages. A column on the row, so it narrows the query rather than the page.",
|
|
4156
|
+
"schema": {
|
|
4157
|
+
"type": "boolean"
|
|
4158
|
+
}
|
|
4159
|
+
},
|
|
4160
|
+
{
|
|
4161
|
+
"name": "attachments",
|
|
4162
|
+
"in": "query",
|
|
4163
|
+
"required": false,
|
|
4164
|
+
"description": "When true, return only messages carrying an attachment. A column on the row, so it narrows the query rather than the page.",
|
|
4165
|
+
"schema": {
|
|
4166
|
+
"type": "boolean"
|
|
4167
|
+
}
|
|
4168
|
+
},
|
|
4169
|
+
{
|
|
4170
|
+
"name": "count",
|
|
4171
|
+
"in": "query",
|
|
4172
|
+
"required": false,
|
|
4173
|
+
"description": "Include how many messages the listing matches. Counted over the whole scope, independent of `limit`.",
|
|
4174
|
+
"schema": {
|
|
4175
|
+
"type": "boolean"
|
|
4176
|
+
}
|
|
4177
|
+
},
|
|
4178
|
+
{
|
|
4179
|
+
"name": "results",
|
|
4180
|
+
"in": "query",
|
|
4181
|
+
"required": false,
|
|
4182
|
+
"description": "Return matching rows. Default true; set false for a count-only response.",
|
|
4183
|
+
"schema": {
|
|
4184
|
+
"type": "boolean"
|
|
4185
|
+
}
|
|
3910
4186
|
}
|
|
3911
4187
|
],
|
|
3912
4188
|
"responses": {
|
|
@@ -3915,26 +4191,7 @@
|
|
|
3915
4191
|
"content": {
|
|
3916
4192
|
"application/json": {
|
|
3917
4193
|
"schema": {
|
|
3918
|
-
"
|
|
3919
|
-
"required": [
|
|
3920
|
-
"items"
|
|
3921
|
-
],
|
|
3922
|
-
"properties": {
|
|
3923
|
-
"continuationToken": {
|
|
3924
|
-
"allOf": [
|
|
3925
|
-
{
|
|
3926
|
-
"$ref": "#/components/schemas/String800"
|
|
3927
|
-
}
|
|
3928
|
-
],
|
|
3929
|
-
"description": "Opaque, server-minted cursor: absent means the first (or last) page, present means resume from here. Echo it back unchanged to fetch the next page. Every listing endpoint that accepts it rejects a token it cannot decode with 400 ValidationError rather than silently restarting from the first page (#136, #172)."
|
|
3930
|
-
},
|
|
3931
|
-
"items": {
|
|
3932
|
-
"type": "array",
|
|
3933
|
-
"items": {
|
|
3934
|
-
"$ref": "#/components/schemas/RemitImap.ThreadMessageResponse"
|
|
3935
|
-
}
|
|
3936
|
-
}
|
|
3937
|
-
}
|
|
4194
|
+
"$ref": "#/components/schemas/RemitImap.ThreadSearchResponse"
|
|
3938
4195
|
}
|
|
3939
4196
|
}
|
|
3940
4197
|
}
|
|
@@ -5343,6 +5600,73 @@
|
|
|
5343
5600
|
],
|
|
5344
5601
|
"description": "Projection of a VEVENT's STATUS property (RFC 5545 3.8.1.11). A VEVENT with no STATUS projects as `Confirmed`, which is the value RFC 5545 gives an event whose status is unstated."
|
|
5345
5602
|
},
|
|
5603
|
+
"RemitImap.CalendarFeedResponse": {
|
|
5604
|
+
"type": "object",
|
|
5605
|
+
"required": [
|
|
5606
|
+
"calendarId",
|
|
5607
|
+
"feedToken",
|
|
5608
|
+
"createdAt",
|
|
5609
|
+
"rotatedAt"
|
|
5610
|
+
],
|
|
5611
|
+
"properties": {
|
|
5612
|
+
"calendarId": {
|
|
5613
|
+
"allOf": [
|
|
5614
|
+
{
|
|
5615
|
+
"$ref": "#/components/schemas/UUID"
|
|
5616
|
+
}
|
|
5617
|
+
],
|
|
5618
|
+
"description": "Collection this address serves"
|
|
5619
|
+
},
|
|
5620
|
+
"feedToken": {
|
|
5621
|
+
"allOf": [
|
|
5622
|
+
{
|
|
5623
|
+
"$ref": "#/components/schemas/String512"
|
|
5624
|
+
}
|
|
5625
|
+
],
|
|
5626
|
+
"description": "The token itself, base64url over 32 random bytes. It is the whole credential: the path `/feeds/calendar/{feedToken}.ics` needs nothing else, which is what lets a client that cannot sign in subscribe."
|
|
5627
|
+
},
|
|
5628
|
+
"createdAt": {
|
|
5629
|
+
"type": "integer",
|
|
5630
|
+
"format": "int64",
|
|
5631
|
+
"description": "When this calendar first got a feed address"
|
|
5632
|
+
},
|
|
5633
|
+
"rotatedAt": {
|
|
5634
|
+
"type": "integer",
|
|
5635
|
+
"format": "int64",
|
|
5636
|
+
"description": "When the token was last replaced. `0` means it is still the first one."
|
|
5637
|
+
}
|
|
5638
|
+
},
|
|
5639
|
+
"description": "A calendar's secret subscription address, with the token in the clear.\n\nReturned by the write that mints it and nowhere else. Only the hash is\nstored, so a client that loses this value rotates the feed rather than\nreading it back — which is also what makes the read side safe to leave\ntokenless."
|
|
5640
|
+
},
|
|
5641
|
+
"RemitImap.CalendarFeedStateResponse": {
|
|
5642
|
+
"type": "object",
|
|
5643
|
+
"required": [
|
|
5644
|
+
"calendarId",
|
|
5645
|
+
"createdAt",
|
|
5646
|
+
"rotatedAt"
|
|
5647
|
+
],
|
|
5648
|
+
"properties": {
|
|
5649
|
+
"calendarId": {
|
|
5650
|
+
"allOf": [
|
|
5651
|
+
{
|
|
5652
|
+
"$ref": "#/components/schemas/UUID"
|
|
5653
|
+
}
|
|
5654
|
+
],
|
|
5655
|
+
"description": "Collection this address serves"
|
|
5656
|
+
},
|
|
5657
|
+
"createdAt": {
|
|
5658
|
+
"type": "integer",
|
|
5659
|
+
"format": "int64",
|
|
5660
|
+
"description": "When this calendar first got a feed address"
|
|
5661
|
+
},
|
|
5662
|
+
"rotatedAt": {
|
|
5663
|
+
"type": "integer",
|
|
5664
|
+
"format": "int64",
|
|
5665
|
+
"description": "When the token was last replaced. `0` means it is still the first one."
|
|
5666
|
+
}
|
|
5667
|
+
},
|
|
5668
|
+
"description": "Whether a calendar has a feed address, and how old it is. The token is deliberately absent — it exists in the clear once, in the answer to the write that minted it."
|
|
5669
|
+
},
|
|
5346
5670
|
"RemitImap.CalendarFreeBusyResponse": {
|
|
5347
5671
|
"type": "object",
|
|
5348
5672
|
"required": [
|
|
@@ -9371,10 +9695,10 @@
|
|
|
9371
9695
|
"count": {
|
|
9372
9696
|
"type": "integer",
|
|
9373
9697
|
"format": "int32",
|
|
9374
|
-
"description": "How
|
|
9698
|
+
"description": "How much the query matches, over the whole scope and independent of `limit`.\nPresent only when `count=true`.\n\nEach operation counts what it lists. `searchThreads` lists messages of one\nmailbox and counts messages; with `senderTrust` or `dkimMismatch` in the\nquery that count is over the enriched window instead, since those are\nresolved off the row. `listAllThreads` counts CONVERSATIONS across every\nnon-muted mailbox of every account — a thread holding two matching messages\ncounts once, and so does one message reachable through a real folder and a\nvirtual copy of it — because that is what the cross-account listing renders\nafter collapsing by `threadId`. A count that disagreed with the rows beneath\nit would be a third number for the same set."
|
|
9375
9699
|
}
|
|
9376
9700
|
},
|
|
9377
|
-
"description": "Aggregate response for `searchThreads`. Carries the matching rows (`items`), a\
|
|
9701
|
+
"description": "Aggregate response for the filterable thread listings — `searchThreads` and\n`listAllThreads`. Carries the matching rows (`items`), a pagination\n`continuationToken`, and an optional `count` of what the query matches.\n`items` is omitted when `results=false` (count-only); `count` is present only\nwhen `count=true`. Thread-specific so the shared `ResultList<T>` (7 endpoints)\nstays untouched.\n\n`listAllThreads` answers with this model rather than `ResultList<T>` for that\nsame reason: it needs the count field and the shared model cannot carry one.\nOne model over both operations rather than a second of the same shape, so a\nclient reading a filtered thread listing reads one response type whether the\nlisting is scoped to a mailbox or spans every account."
|
|
9378
9702
|
},
|
|
9379
9703
|
"RemitImap.TrustedFlag": {
|
|
9380
9704
|
"type": "object",
|