-
Notifications
You must be signed in to change notification settings - Fork 52
feature/jwks validator #1103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feature/jwks validator #1103
Changes from all commits
40cdd35
a8f5b25
c7ea1bb
c8aa4bf
6802ebe
bb8a016
1644ad3
9afb72a
39050cf
24b4490
17909ea
0b48b6f
de13f35
51e46ec
8929a76
24d46db
40a4e6b
d65d37c
66e04e4
72c073a
14b164a
d587da3
f5b3ef5
4df7584
fb4f2ea
5c88be6
0c984c5
6b7bcb4
7cbde6f
9d32b44
bd729dc
751f0ba
c1b3c20
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,7 @@ logs | |
| **/*.tgz | ||
| *.zip | ||
| *.tgz | ||
| .npmrc | ||
|
|
||
| smoke/package.json | ||
| smoke/pnpm-lock.yaml | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -106,6 +106,14 @@ export class CRDTImpl implements CRDT { | |||||||||||||||||||||||||||||||||||||||
| const crdtMeta = meta as CRDTMeta; | ||||||||||||||||||||||||||||||||||||||||
| if (!crdtMeta.head) throw this.logger.Error().Msg("missing head").AsError(); | ||||||||||||||||||||||||||||||||||||||||
| // console.log("applyMeta-pre", crdtMeta.head, this.clock.head); | ||||||||||||||||||||||||||||||||||||||||
| this.logger | ||||||||||||||||||||||||||||||||||||||||
| .Debug() | ||||||||||||||||||||||||||||||||||||||||
| .Str("newHead", crdtMeta.head.map((h) => h.toString()).join(",")) | ||||||||||||||||||||||||||||||||||||||||
| .Int("subscribers", this.clock.watchers.size + this.clock.noPayloadWatchers.size) | ||||||||||||||||||||||||||||||||||||||||
| .Int("headLength", crdtMeta.head.length) | ||||||||||||||||||||||||||||||||||||||||
| .Int("currentHeadLength", this.clock.head.length) | ||||||||||||||||||||||||||||||||||||||||
| .Str("dbName", this.opts.name || "unnamed") | ||||||||||||||||||||||||||||||||||||||||
| .Msg("APPLY_META: Calling applyHead for REMOTE sync"); | ||||||||||||||||||||||||||||||||||||||||
| await this.clock.applyHead(crdtMeta.head, []); | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+109
to
117
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Pass the current head as prevHead in applyMeta; avoid using an empty prevHead. Using [] as prevHead causes downstream code (clockChangesSince) to treat the change as “since genesis,” potentially flooding subscribers with all historical updates on each remote sync. Pass a snapshot of the current head instead. - await this.clock.applyHead(crdtMeta.head, []);
+ const prevHead = [...this.clock.head];
+ await this.clock.applyHead(crdtMeta.head, prevHead);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| // console.log("applyMeta-post", crdtMeta.head, this.clock.head); | ||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -184,6 +192,15 @@ export class CRDTImpl implements CRDT { | |||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||
| return { head }; | ||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||
| this.logger | ||||||||||||||||||||||||||||||||||||||||
| .Debug() | ||||||||||||||||||||||||||||||||||||||||
| .Str("newHead", done.meta.head.map((h) => h.toString()).join(",")) | ||||||||||||||||||||||||||||||||||||||||
| .Int("subscribers", this.clock.watchers.size + this.clock.noPayloadWatchers.size) | ||||||||||||||||||||||||||||||||||||||||
| .Int("headLength", done.meta.head.length) | ||||||||||||||||||||||||||||||||||||||||
| .Int("prevHeadLength", prevHead.length) | ||||||||||||||||||||||||||||||||||||||||
| .Int("currentHeadLength", this.clock.head.length) | ||||||||||||||||||||||||||||||||||||||||
| .Str("dbName", this.opts.name || "unnamed") | ||||||||||||||||||||||||||||||||||||||||
| .Msg("BULK: Calling applyHead for LOCAL write"); | ||||||||||||||||||||||||||||||||||||||||
| await this.clock.applyHead(done.meta.head, prevHead, updates); | ||||||||||||||||||||||||||||||||||||||||
| return done.meta; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -36,7 +36,7 @@ | |||||||||||||||||||||||||||||||||
| "url": "https://github.com/fireproof-storage/fireproof/issues" | ||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||
| "dependencies": { | ||||||||||||||||||||||||||||||||||
| "@adviser/cement": "^0.4.25", | ||||||||||||||||||||||||||||||||||
| "@adviser/cement": "^0.4.26", | ||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainVerify repo-wide version alignment and lockfile refresh. Ensure all packages (deps, devDeps, peerDeps) consistently reference @adviser/cement ^0.4.26 and refresh the workspace lockfile to avoid mixed resolutions. Run this script from repo root to surface any mismatches (e.g., deps vs peerDeps): 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo -e "File\tdep\tdevDep\tpeerDep"
fd -a -H package.json | while read -r f; do
jq -r --arg PKG "@adviser/cement" '
. as $root
| [
input_filename,
($root.dependencies[$PKG] // ""),
($root.devDependencies[$PKG] // ""),
($root.peerDependencies[$PKG] // "")
] | @tsv
' "$f" 2>/dev/null
done | sort
echo
echo "Mismatches (dependency != peerDependency):"
fd -a -H package.json | while read -r f; do
jq -r --arg PKG "@adviser/cement" '
. as $root
| ($root.dependencies[$PKG] // "") as $dep
| ($root.peerDependencies[$PKG] // "") as $peer
| if ($dep != "" and $peer != "" and $dep != $peer) then
(input_filename + "\tdep=" + $dep + "\tpeer=" + $peer)
else empty end
' "$f" 2>/dev/null
doneLength of output: 11352 Align @adviser/cement versions across all packages & refresh lockfile It looks like two consumer packages are still on older versions of Files to update:
Suggested diffs: --- core/jwks/package.json
+++ core/jwks/package.json
@@ -12,7 +12,7 @@
"dependencies": {
- "@adviser/cement": "^0.4.25",
+ "@adviser/cement": "^0.4.26",
/* … */
}
}--- examples/react-router/package.json
+++ examples/react-router/package.json
@@ -8,7 +8,7 @@
"dependencies": {
- "@adviser/cement": "^0.4.21",
+ "@adviser/cement": "^0.4.26",
/* … */
}
}Once these are updated, run your package manager’s install command (e.g. 📝 Committable suggestion
Suggested change
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| "@fireproof/core-blockstore": "workspace:0.0.0", | ||||||||||||||||||||||||||||||||||
| "@fireproof/core-keybag": "workspace:0.0.0", | ||||||||||||||||||||||||||||||||||
| "@fireproof/core-runtime": "workspace:0.0.0", | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| import { toSortedObject } from "@adviser/cement/utils"; | ||
| import { Base64EndeCoder } from "@fireproof/core-types-base"; | ||
| import { decodeJwt } from "jose"; | ||
| import { base58btc } from "multiformats/bases/base58"; | ||
| import { sha1 } from "multiformats/hashes/sha1"; | ||
| import { sha256 } from "multiformats/hashes/sha2"; | ||
| import { CertificatePayload, CertificatePayloadSchema } from "@fireproof/core-types-base/fp-ca-cert-payload.zod.js"; | ||
|
|
||
| export class Certor { | ||
| readonly #cert: CertificatePayload; | ||
| readonly base64: Base64EndeCoder; | ||
| #strCert?: string; | ||
| #uint8Cert?: Uint8Array; | ||
|
|
||
| static fromString(base64: Base64EndeCoder, cert: string) { | ||
| const certObj = CertificatePayloadSchema.parse(JSON.parse(base64.decode(cert))); | ||
| return new Certor(base64, certObj); | ||
| } | ||
|
|
||
| static fromJWT(base64: Base64EndeCoder, jwtString: string) { | ||
| // const header = decodeProtectedHeader(jwtString); | ||
| const payload = decodeJwt(jwtString); | ||
| const certObj = CertificatePayloadSchema.parse(payload); | ||
| return new Certor(base64, certObj); | ||
| } | ||
|
|
||
| constructor(base64: Base64EndeCoder, cert: CertificatePayload) { | ||
| this.#cert = cert; | ||
| this.base64 = base64; | ||
| } | ||
|
|
||
| asCert(): CertificatePayload { | ||
| return this.#cert; | ||
| } | ||
|
|
||
| parseCertificateSubject(s: string): Record<string, string> { | ||
| const parts: Record<string, string> = {}; | ||
| s.split(",").forEach((part) => { | ||
| const [key, value] = part.trim().split("="); | ||
| if (key && value) { | ||
| parts[key] = value; | ||
| } | ||
| }); | ||
| return parts; | ||
| } | ||
|
|
||
| async asSHA1() { | ||
| this.#uint8Cert ||= this.base64.decodeUint8(this.asBase64()); | ||
| const val = await sha1.digest(this.#uint8Cert); | ||
| return base58btc.encode(val.bytes); | ||
| } | ||
|
|
||
| async asSHA256() { | ||
| this.#uint8Cert ||= this.base64.decodeUint8(this.asBase64()); | ||
| const val = await sha256.digest(this.#uint8Cert); | ||
| return base58btc.encode(val.bytes); | ||
| } | ||
|
|
||
| asBase64() { | ||
| this.#strCert ||= this.base64.encode(JSON.stringify(toSortedObject(this.#cert))); | ||
| return this.#strCert; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid duplicate noPayloadWatcher invocations when changes > 0.
In the manual path you call notifyWatchers(changes.result), which already triggers noPayloadWatchers, and then you invoke noPayloadWatchers again — leading to duplicate tock callbacks.
if (changes.result.length > 0) { this.logger.Debug().Msg("MANUAL_NOTIFICATION: Calling notifyWatchers with changes"); - this.notifyWatchers(changes.result); - this.noPayloadWatchers.forEach((fn) => fn()); + this.notifyWatchers(changes.result); } else { this.logger.Debug().Msg("MANUAL_NOTIFICATION: Calling noPayloadWatchers directly"); this.noPayloadWatchers.forEach((fn) => fn()); }📝 Committable suggestion
🤖 Prompt for AI Agents