@everystack/api 0.4.1 → 0.4.3

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/CHANGELOG.md CHANGED
@@ -4,13 +4,90 @@ All notable changes to `@everystack/api` are documented here.
4
4
 
5
5
  Format based on [Keep a Changelog](https://keepachangelog.com/).
6
6
 
7
- ## [Unreleased]
7
+ ## [0.4.3] - 2026-10-14
8
+
9
+ ### BREAKING CHANGES
10
+
11
+ - rowOwnership fails closed
12
+ - a public route with a token answers 503 when the verifier is down
13
+
14
+ ### Added
15
+
16
+ - a throwing after-hook reaches onError as kind 'hook'
17
+
18
+ ### Fixed
19
+
20
+ - guard explicit hidden column query references
21
+ - check select depth before hidden column traversal
22
+ - audit refused hidden column requests
23
+ - exclude hidden columns from relation embeds
24
+ - resolve embed exclusions by column identity
25
+ - fail closed on unresolved embed hidden columns
26
+ - warn on invalid hidden column configuration
27
+ - rowOwnership exceptRoles lifts the backstop for manage roles
28
+ - an excepted role must filter its PATCH; role claim must be a string
29
+ - a write filter must build a SQL condition
30
+ - an infrastructure outage answers 503, never 401, and never leaks driver text
31
+ - classify a wrapped outage cause, and close the review findings
32
+ - the outage 503 is never cached
33
+ - an empty owner value is not an owner
34
+ - an owner cannot reassign the ownership column
35
+ - rowOwnership throws on an unknown table
36
+ - a non-string role claim never satisfies a role gate
37
+ - rowOwnership.exceptRoles requires pgSettings
38
+ - an excepted write needs a role from pgSettings
39
+ - the unbacked-exemption 500 reaches onError
40
+ - a throwing before-hook reaches onError
41
+ - an auth outage 503 reaches onError
42
+ - the auth-outage report never throws and names only known routes
43
+ - an RPC name resolves only to an own key of rpc
44
+ - a JWKS timeout and a bad service credential answer 503
45
+ - a table request that hits an outage answers 503
46
+ - an outage fault names only a declared RPC
47
+ - reporting a fault never throws on an unreadable error
48
+ - an outage inside a before-hook answers 503
49
+ - an after-hook fault no longer claims the write committed
50
+ - after-hooks run after the commit
51
+ - before-hook faults are reported after the transaction
52
+ - guard every read of a thrown value in the handler
53
+ - resolve embeds and table-name twins by own keys only
54
+
55
+ ### Documentation
56
+
57
+ - say that an RPC name resolves only to an own key
58
+ - say why the 2xx guard stands and what a retry wrapper must reset
59
+ - rowOwnership exceptRoles
60
+ - rowOwnership fails closed, and createHandler validates it
61
+ - name the breaks, and correct the non-owner write response
62
+ - an owner cannot change the ownership column on PATCH
63
+ - the protectedFields strip is per spelling; the owner compare is on strings
64
+ - rowOwnership refuses a table it cannot find anywhere
65
+ - say what the unknown-table check cannot catch
66
+ - a thrown non-Error has no stack in the onError fault
67
+ - tell a verifier that logs in as the caller to catch class 28
68
+ - publicRoutes and publicRpc skip the token, not the client check
69
+ - afterRpc runs after the commit, the table after-hooks before it
70
+
71
+ ## [0.4.2] - 2026-09-22
72
+
73
+ ### Fixed
74
+
75
+ - refresh expired JWT instead of silently failing every request
76
+
77
+ ## [0.4.1] - 2026-09-22
8
78
 
9
79
  ### Added
10
80
 
11
81
  - auto-generated changelogs from conventional commits
12
82
  - automate the version-drift check — a manual note is not a gate
13
83
 
84
+ ### Fixed
85
+
86
+ - coerce date-typed column values before insert/update
87
+ - review follow-ups on date-column coercion
88
+ - second review pass -- ISO strictness, null rows, sibling array-safety
89
+ - reject offset-less datetime strings (ambiguous: server-local, not UTC)
90
+
14
91
  ## [0.4.0] - 2026-07-14
15
92
 
16
93
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everystack/api",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "PostgREST-compatible HTTP handler + typed fetch client for Drizzle ORM",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": "Scalable Technology, Inc. <licensing@scalable.technology>",
@@ -13,6 +13,8 @@ export interface ClientOptions {
13
13
  getToken?: () => string | null | Promise<string | null>;
14
14
  /** Called on 401 — return a new token to retry, or null to fail */
15
15
  onTokenExpired?: () => Promise<string | null>;
16
+ /** Called when a 401 could not be recovered — refresh failed, or the retry with the refreshed token also 401/403'd */
17
+ onAuthFailure?: () => void;
16
18
  /** Client credentials sent with every request */
17
19
  clientCredentials?: {
18
20
  id: string;
@@ -296,6 +298,8 @@ async function fetchWithRetry(
296
298
  const retryResponse = await fetch(url, { ...init, headers: retryHeaders });
297
299
 
298
300
  if (!retryResponse.ok) {
301
+ // Refreshed token was still rejected — unrecoverable.
302
+ options.onAuthFailure?.();
299
303
  return { retried: { data: null, error: await parseError(retryResponse) } };
300
304
  }
301
305
 
@@ -303,7 +307,8 @@ async function fetchWithRetry(
303
307
  return { response: retryResponse };
304
308
  }
305
309
 
306
- // Refresh failed
310
+ // Refresh failed — unrecoverable.
311
+ options.onAuthFailure?.();
307
312
  return { retried: { data: null, error: await parseError(response) } };
308
313
  }
309
314