Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
932 commits
Select commit Hold shift + click to select a range
93248e9
Give per-owner namespaces one reconciler that owns them
karthik1729 Aug 27, 2026
dc081ec
Stop the ownerbinding status write from triggering itself
karthik1729 Aug 27, 2026
7501e78
Make a workspace create its volume and wait for the disk
karthik1729 Aug 27, 2026
bc4c2de
Validate a workspace's git source before it becomes an ssh argv
karthik1729 Aug 27, 2026
3d8eae7
Make a push an object with its own reconciler
karthik1729 Aug 27, 2026
73aa0b7
Gate an environment's teardown on its stop snapshot landing
karthik1729 Aug 27, 2026
bf28fc8
Stop an environment reconciling its own stop into a second push
karthik1729 Aug 27, 2026
9cd9dbd
Give an environment a Volume child of its own
karthik1729 Aug 27, 2026
0608493
Share one volume resolution between both parent reconcilers
karthik1729 Aug 27, 2026
c6cdc63
Adopt pre-migration volumes and backfill their history
karthik1729 Aug 27, 2026
2019b93
Make the startup migration non-fatal and its status writes replayable
karthik1729 Aug 27, 2026
0e01f69
Write one object per user action in the workspaces API
karthik1729 Aug 27, 2026
23647be
Show a snapshot by when and what it says, not by its layers
karthik1729 Aug 27, 2026
94bed05
Narrow the API's RBAC and size a legacy clone from its volume
karthik1729 Aug 27, 2026
ce56a7c
Prove git seeding end to end and pin the roll order
karthik1729 Aug 27, 2026
6b402f0
Install the workspace key before waiting on a seeded pod
karthik1729 Aug 27, 2026
930617d
Close the final review gaps in the node controller
karthik1729 Aug 27, 2026
143456b
Move off the yanked chacha20 0.10.1
karthik1729 Aug 27, 2026
a7f45cf
Rewrite the README as an architecture map
karthik1729 Aug 27, 2026
aaf01ef
Roll the agent, api and web onto controller ownership
karthik1729 Aug 27, 2026
aba30df
Let the agent Secret alone name its region
karthik1729 Aug 27, 2026
f18d468
Let a region be retired and never offer it to new workspaces
karthik1729 Aug 27, 2026
3db4600
Wake the agent's reconciler when its btrfs work finishes
karthik1729 Aug 27, 2026
11fb164
Narrow the reconcile_on feature gate and cover its success path
karthik1729 Aug 27, 2026
0fa2b3f
Roll onto the wake-on-completion agent and region retirement
karthik1729 Aug 27, 2026
5713b00
Poll faster while a workspace or environment is coming up
karthik1729 Aug 27, 2026
1499e0a
Roll the web onto the fast list poll
karthik1729 Aug 27, 2026
3138f51
Serve volume listings and snapshot history from the browse tier
karthik1729 Aug 27, 2026
104d530
Read snapshots from the server tier instead of the cluster
karthik1729 Aug 27, 2026
00a9327
Show snapshots whose source workspace is gone
karthik1729 Aug 27, 2026
9976791
Record that snapshots are the server tier's, not the cluster's
karthik1729 Aug 27, 2026
da3e644
Cover environment snapshots in the volume listing
karthik1729 Aug 27, 2026
f400879
Resolve snapshot listing review findings
karthik1729 Aug 27, 2026
6a3ff48
Roll the web onto server-tier snapshots
karthik1729 Aug 27, 2026
71de4b2
Roll the agent and server tier onto server-tier snapshots
karthik1729 Aug 27, 2026
2072818
Hide volumes that hold no snapshot from the listing
karthik1729 Aug 27, 2026
8d8baa4
Roll the server tier onto the trimmed snapshot listing
karthik1729 Aug 27, 2026
47bc55d
Restore a snapshot from the region its bytes live in
karthik1729 Aug 27, 2026
3cac885
Bound every blob read so a restore cannot hang
karthik1729 Aug 27, 2026
29819ec
Show an environment's snapshots on the environment
karthik1729 Aug 27, 2026
d1560c1
Restore a team's snapshot as the team, from the team's volume
karthik1729 Aug 27, 2026
0b197ab
Roll onto environment snapshots and cross-region restore
karthik1729 Aug 27, 2026
7becc32
Restore an environment in place, as a wish the controllers grant
karthik1729 Aug 28, 2026
7a87217
Split the environments list into live and archived groups
karthik1729 Aug 28, 2026
c64c7b3
Give an environment its own page, with Services and Snapshots tabs
karthik1729 Aug 28, 2026
57531ea
Report a restoring environment as running, not as an unknown phase
karthik1729 Aug 28, 2026
577feed
Make a repeated restore work and a failed one leave nothing behind
karthik1729 Aug 28, 2026
b6614c3
Roll onto the environment page and in-place restore
karthik1729 Aug 28, 2026
0562e74
Enter an environment the way you enter a code repo
karthik1729 Aug 28, 2026
3b90b26
Show live services only, and say that is what they are
karthik1729 Aug 28, 2026
b2c695c
Roll the web onto the environment chrome
karthik1729 Aug 28, 2026
bdda462
Roll the web onto live-services naming
karthik1729 Aug 28, 2026
efe72c0
Keep dynamic page segments in the client cache for 30s
karthik1729 Aug 28, 2026
75887c2
Roll the web onto the client cache TTL
karthik1729 Aug 28, 2026
e0c08a4
Show where the environment sits in its snapshot lineage
karthik1729 Aug 28, 2026
d1dde8e
Roll the web onto the lineage view
karthik1729 Aug 28, 2026
53cd560
Keep the environment tab row constant and name it in the crumb
karthik1729 Aug 28, 2026
f93e50d
Roll the web onto the constant environment chrome
karthik1729 Aug 28, 2026
e2629dd
Draw the snapshot lineage on one rail and give environments a setting…
karthik1729 Aug 28, 2026
f53e8f0
Delete one snapshot record from a volume's history
karthik1729 Aug 28, 2026
c0957e4
Roll the web onto the lineage rail and environment settings
karthik1729 Aug 28, 2026
76dfc94
Expose one-snapshot delete on the workspaces api
karthik1729 Aug 28, 2026
5a7d190
Let a single snapshot be deleted from the lineage
karthik1729 Aug 28, 2026
52ebf98
Walk a snapshot ref back before its record goes
karthik1729 Aug 28, 2026
8ba1687
Roll the server tier and web onto per-snapshot delete
karthik1729 Aug 28, 2026
24754bb
Wait for a restore's pods to exit in the pass that scaled them down
karthik1729 Aug 28, 2026
ec8d5d1
Draw the snapshot history as a tree with the live environment at its …
karthik1729 Aug 28, 2026
e45654a
Pin the api, web and agent images to ec8d5d1
karthik1729 Aug 28, 2026
3278d5a
Draw the snapshot tree as lanes in a gutter instead of nested indenta…
karthik1729 Aug 28, 2026
1b24be0
Pin the web image to 3278d5a
karthik1729 Aug 28, 2026
8cf1a08
Land the sign-in link in a Route Handler so the session cookie can be…
karthik1729 Aug 28, 2026
ea48db0
Pin the web image to 8cf1a08
karthik1729 Aug 28, 2026
521e2db
Draw the snapshot lineage as the landing panel's rail, newest first
karthik1729 Aug 28, 2026
624d8a8
Pin the web image to 521e2db
karthik1729 Aug 28, 2026
8dc020f
Make Restore the one action and disclose the safety snapshot on request
karthik1729 Aug 28, 2026
da986e4
Pin the web image to 8dc020f
karthik1729 Aug 28, 2026
1920c9f
Restore in place without a name, warn that changes are discarded, kee…
karthik1729 Aug 28, 2026
3dd02fc
Pin the web image to 1920c9f
karthik1729 Aug 28, 2026
07e1ac6
Keep an environment's services to one pod per subvolume: stable env o…
karthik1729 Aug 28, 2026
6c152de
Pin the agent image to 07e1ac6
karthik1729 Aug 28, 2026
32b724d
Run each environment service as a StatefulSet so one subvolume never …
karthik1729 Aug 28, 2026
c9baa4a
Point the agent's reconcile tests at StatefulSets
karthik1729 Aug 28, 2026
ec16056
Pin the agent image to c9baa4a
karthik1729 Aug 28, 2026
c4af21f
Design: declarative workspace packages on a host Nix store
karthik1729 Aug 28, 2026
576ad55
Design: package list lives on the subvolume and is installed on every…
karthik1729 Aug 28, 2026
80ba6a8
Design: the package list is kloudlite.yaml in the repository, nothing…
karthik1729 Aug 28, 2026
c6ed049
Plan the workspace packages implementation
karthik1729 Aug 28, 2026
bbcd391
Parse and validate a workspace's kloudlite.yaml package list
karthik1729 Aug 28, 2026
0557f9e
Reject YAML tags/anchors/aliases by scanning for their characters any…
karthik1729 Aug 28, 2026
0f81c4b
Strip only whole-line comments before the anchor/tag character scan
karthik1729 Aug 28, 2026
a406a70
Report a workspace's package profile on its status
karthik1729 Aug 28, 2026
fa92b9d
Mount the host Nix store and the workspace's own profile read-only in…
karthik1729 Aug 28, 2026
fe9cb51
Design and plan: the package list is the Workspace spec, not a repo file
karthik1729 Aug 28, 2026
e392c78
Carry a workspace's package list on its spec
karthik1729 Aug 28, 2026
bb80d80
Add packages field to the agent test's WorkspaceSpec literal
karthik1729 Aug 28, 2026
766f8a5
Give the agent a Nix runner that builds and publishes profiles by rename
karthik1729 Aug 28, 2026
73bf7c7
Drain nix's pipes while it runs and kill its process group on timeout
karthik1729 Aug 28, 2026
0e50e98
Build a workspace's Nix profile from its spec before its pod
karthik1729 Aug 28, 2026
d9a8b82
Build every workspace's profile, and keep a failed build retryable
karthik1729 Aug 28, 2026
10edc82
Collect Nix garbage from the janitor when the store grows past its th…
karthik1729 Aug 28, 2026
d56ab87
Stop the janitor's Nix GC walk from following symlinks or blocking th…
karthik1729 Aug 28, 2026
bc8c0c3
Let a workspace's packages be set at create and changed later
karthik1729 Aug 28, 2026
ceeb9a9
Run a Nix store and daemon on every pool node from the agent DaemonSet
karthik1729 Aug 28, 2026
acf6696
Apply nix-conf.yaml alongside the agent DaemonSet in the migration ru…
karthik1729 Aug 28, 2026
8be4702
Exercise workspace packages end to end: spec to PATH, live swap, clone
karthik1729 Aug 28, 2026
05f6841
Make a workspace profile a directory rooted against the collector
karthik1729 Aug 28, 2026
129ace0
Rebuild a profile whose spec changed while it was building
karthik1729 Aug 28, 2026
22c905d
Refuse to start on an unpinned nixpkgs and root the profiles tree
karthik1729 Aug 28, 2026
35decd7
Keep a profile build honest across a restart and an old layout
karthik1729 Aug 28, 2026
33100b4
Wait for the restarted build to run before counting it
karthik1729 Aug 28, 2026
6b9c7c1
Pin the agent and server images to 33100b4, web to 8be4702
karthik1729 Aug 28, 2026
3c71a52
Run workspaces on bare alpine with a platform base set of Nix packages
karthik1729 Aug 28, 2026
304dc78
Pin the agent, server and web images to 3c71a52
karthik1729 Aug 28, 2026
cee17bf
Delete unused shadcn dropdown-menu parts
karthik1729 Aug 28, 2026
b190251
Delete unused landing loop visual and its keyframes
karthik1729 Aug 28, 2026
2de64ca
Delete unused input-group button/text/input/textarea parts
karthik1729 Aug 28, 2026
60306c5
Delete unused avatar image/badge/group parts
karthik1729 Aug 28, 2026
30a0db0
Delete unused select group/label/separator parts
karthik1729 Aug 28, 2026
03e904a
Delete unused command/kbd exports and dialog part re-exports
karthik1729 Aug 28, 2026
dc8cacc
Drop now-unused DialogClose helper and dropdown-menu icon imports
karthik1729 Aug 28, 2026
124e00f
Delete the agent placement module nothing calls
karthik1729 Aug 28, 2026
7bb6456
Drop the agent boot migration now the cluster carries nothing legacy
karthik1729 Aug 28, 2026
c1192e2
Drop three one-off throughput benches
karthik1729 Aug 28, 2026
3b71dfb
Drop the Mongo-era repo-marker backfill command
karthik1729 Aug 28, 2026
2eb13eb
Drop the ws-tests workflow nothing consumes
karthik1729 Aug 28, 2026
f072ee2
Read the fleet variables inside fleet_guard
karthik1729 Aug 28, 2026
baaa1ee
Fix the stale ssh_fingerprint doc comment
karthik1729 Aug 28, 2026
bfa2292
Fold the three backstop lanes into one spawner
karthik1729 Aug 28, 2026
27a0cf6
Read gc owner prefixes through one helper
karthik1729 Aug 28, 2026
b0618b0
Inline the agent settings no manifest sets
karthik1729 Aug 28, 2026
80ece80
Drop the Entra env the web app has no provider for
karthik1729 Aug 28, 2026
c90d0cb
Collapse MetaStore to its region half and drop fsck
karthik1729 Aug 28, 2026
581b689
Delete five declared but unreferenced dependencies
karthik1729 Aug 28, 2026
bc021b1
Drop the bytes direct dep in favour of slatedb::bytes
karthik1729 Aug 28, 2026
068262d
Take squash's three fields instead of an unreachable workspace lookup
karthik1729 Aug 28, 2026
b23b5f8
Fold the nix PV and claim into the parameterised builders
karthik1729 Aug 28, 2026
5eea437
Delete the unused ~/.aws profile loader
karthik1729 Aug 28, 2026
dc621e3
Send every owner-node request through one to_owner
karthik1729 Aug 28, 2026
417f4e3
Map chunk upload refusals through one helper
karthik1729 Aug 28, 2026
ad85241
Fold the broken Redis stub into the scripted one
karthik1729 Aug 28, 2026
8dbed2a
Route registry client calls through one send
karthik1729 Aug 28, 2026
6b144e1
Give Team a Default instead of two eight-field literals
karthik1729 Aug 28, 2026
0e4f557
Build the pulls query string with form_urlencoded
karthik1729 Aug 28, 2026
aabf0d8
Delete the ignored restore field and the discarded autoclaim cursor
karthik1729 Aug 28, 2026
be5bb10
Keep one labels helper in k8s
karthik1729 Aug 28, 2026
bd1d44d
Pin the agent, server and web images to be5bb10
karthik1729 Aug 28, 2026
146b604
Harden the nodes, rate-limit the ingresses per real client IP, and sc…
karthik1729 Aug 28, 2026
4c9493e
Note how the HTTP origin is locked to Cloudflare
karthik1729 Aug 28, 2026
19ac0ba
Honour a region's agent token only from its nodes' addresses
karthik1729 Aug 28, 2026
9418a60
Pin the server and agent images to 19ac0ba
karthik1729 Aug 28, 2026
f39103a
Design: SSH into workspaces through a Cloudflare-fronted gateway and …
karthik1729 Aug 28, 2026
fe5a1e5
Plan the workspace SSH implementation
karthik1729 Aug 28, 2026
2e97410
Mint single-purpose ssh-session and cli tokens
karthik1729 Aug 28, 2026
f40f04c
Keep SSH key material and issue revocable CLI tokens
karthik1729 Aug 28, 2026
0cdc55f
Cap the codes one anonymous route can leave in memory
karthik1729 Aug 28, 2026
99f177e
Design: the region gateway serves TLS on the nodes behind the Cloudfl…
karthik1729 Aug 28, 2026
f810eee
Mint ssh sessions and keep authorized_keys in every workspace namespace
karthik1729 Aug 28, 2026
1fe8ed9
Design: finish replacing the tunnel with the proxied node gateway
karthik1729 Aug 28, 2026
6640722
Answer the CLI flow in one wire vocabulary and settle its races
karthik1729 Aug 28, 2026
e65734e
Write workspace keys only into namespaces named for their owner
karthik1729 Aug 28, 2026
372dfe0
Run sshd in every default workspace pod with a per-workspace host key
karthik1729 Aug 28, 2026
3973998
Mount authorized_keys as a directory and give sshd its privsep prereq…
karthik1729 Aug 28, 2026
92834cf
Add the workspace SSH gateway
karthik1729 Aug 28, 2026
4c8cf11
Give the gateway the file capability it needs to bind 443
karthik1729 Aug 28, 2026
d52422a
Add the kl CLI: login, list, ssh, ssh-config, proxy
karthik1729 Aug 28, 2026
684c7a1
Harden the kl CLI's config perms, install checksums and proxy exit code
karthik1729 Aug 28, 2026
da6ac61
Approve CLI logins, list CLI tokens, show the ssh one-liner
karthik1729 Aug 28, 2026
efb9ffb
Admit the region gateway's 443 from Cloudflare only; reserve cli
karthik1729 Aug 28, 2026
9db796d
Return to where sign-in was asked for
karthik1729 Aug 28, 2026
96db762
Fix harden-node.sh: CF_CIDRS is env-only, validate before delete
karthik1729 Aug 28, 2026
86fd2a6
Exercise ssh into a workspace end to end
karthik1729 Aug 28, 2026
3ea8354
Skip on gateway not-Ready, and distinguish missing nc from a broken N…
karthik1729 Aug 28, 2026
05f595a
Refuse a workspace name that could inject ssh config
karthik1729 Aug 28, 2026
a789552
Refresh ssh keys in the owner's namespaces by recomputing their names
karthik1729 Aug 28, 2026
c34d08d
Publish only the CLI's own /v1 prefixes at the ingress
karthik1729 Aug 28, 2026
5c58106
Name the device on the CLI approval page
karthik1729 Aug 28, 2026
e076dcb
Spend an ssh session token only once the tunnel is reserved
karthik1729 Aug 28, 2026
59a6bd0
Put the CLI's config in ~/.config/kl and tidy the ssh path
karthik1729 Aug 28, 2026
f2b0674
Guard the pasted ssh one-liner by the same name rule as the config block
karthik1729 Aug 28, 2026
9eb043c
Pin the agent, gateway and server images to 59a6bd0, web to f2b0674
karthik1729 Aug 28, 2026
7db00b6
Grant workspace pods SYS_CHROOT so sshd's privsep monitor can start
karthik1729 Aug 28, 2026
a978fca
Pin the k3s agent to the SYS_CHROOT build
karthik1729 Aug 28, 2026
cc5b2f4
Terminate the gateway's TLS at Cloudflare and serve plain HTTP on the…
karthik1729 Aug 28, 2026
10e404b
Document the NSG rule the gateway's port 80 needs
karthik1729 Aug 28, 2026
d520413
Keep CLI login codes in the directory so any api replica can approve …
karthik1729 Aug 28, 2026
9b15b93
Pin api and web to the directory-backed CLI login
karthik1729 Aug 28, 2026
0f34dc7
Pin the AKS tier to the directory-backed CLI login
karthik1729 Aug 28, 2026
da43555
Turn off sshd StrictModes: the authorized_keys Secret mount is a 1777…
karthik1729 Aug 28, 2026
52178fb
Pin the k3s agent to the StrictModes build
karthik1729 Aug 28, 2026
5046c27
Log into workspaces as kl, not root
karthik1729 Aug 28, 2026
1b6fdbb
Give reqwest a TLS backend explicitly so a standalone kl build can sp…
karthik1729 Aug 28, 2026
189bbbe
Expect the kl login user in the ssh-config test
karthik1729 Aug 28, 2026
5c991f7
Pin the agent and web to the kl-user build
karthik1729 Aug 28, 2026
a67f6ee
Read the git key as kl through its mode, not fsGroup, which broke the…
karthik1729 Aug 28, 2026
a3b5089
Pin the agent to the kl-user build
karthik1729 Aug 28, 2026
3797e7d
Mount authorized_keys readable by kl, who is now the one sshd reads i…
karthik1729 Aug 28, 2026
254e2e9
Pin the agent to the readable-authorized_keys build
karthik1729 Aug 28, 2026
eb1082d
Log into workspaces with zsh and starship, fish alongside, and a Klou…
karthik1729 Aug 28, 2026
c63ac5b
Name the workspace pod's host ws
karthik1729 Aug 28, 2026
c3b4a6e
Pin the agent to the zsh-login build
karthik1729 Aug 28, 2026
0874250
Chown only what the prelude creates in the home; .ssh is a read-only …
karthik1729 Aug 28, 2026
2d92692
Pin the agent to the fixed zsh-login build
karthik1729 Aug 28, 2026
c856b33
Preconfigure git's user.name and user.email in every workspace
karthik1729 Aug 28, 2026
f0f567b
Export git_identity_for
karthik1729 Aug 28, 2026
89b9513
Mount the workspace at ~/workspace
karthik1729 Aug 28, 2026
f6ee9ca
Update the api test stub for OwnerMaterial
karthik1729 Aug 28, 2026
d73cdf2
Update the seeder test for ~/workspace
karthik1729 Aug 28, 2026
47087a2
Pin the AKS tier and the agent to the git-identity and ~/workspace build
karthik1729 Aug 28, 2026
34b5528
Record the repo-wide audit and the plan to fix it
karthik1729 Aug 28, 2026
5bfab80
Compile the images' binaries on the runner instead of inside docker
karthik1729 Aug 29, 2026
9752b58
Never roll back a repo create the owning node did not answer
karthik1729 Aug 29, 2026
aee12f7
Tie a GPG verified badge to the key's registrant, not its uid
karthik1729 Aug 29, 2026
ddeecd0
Enforce ref-name rules in update_refs and make atomic push fail on an…
karthik1729 Aug 29, 2026
eb71c75
Give team namespaces and bindings unambiguous names and admit only va…
karthik1729 Aug 29, 2026
b616788
Check the agent token on forwarded vol-agent requests
karthik1729 Aug 29, 2026
f478ee3
Record the unclaimed-open window found during the vol-agent auth fix
karthik1729 Aug 29, 2026
de0f864
Authenticate git HTTP requests before reading the body and cap concur…
karthik1729 Aug 29, 2026
30090f5
Put the control-plane backup timer and the Cloudflare origin lock in …
karthik1729 Aug 29, 2026
9ad3a00
Clear the snapshot push marker once it lands and make restore mode ex…
karthik1729 Aug 29, 2026
9d606d6
Drop a generated token with the dialog that showed it
karthik1729 Aug 29, 2026
a766766
Stop caching browse reads in Next and send log's count as n
karthik1729 Aug 29, 2026
d7127a4
Send security headers from the web app and catch a root layout throw
karthik1729 Aug 29, 2026
004f3b4
Scope registry blob pulls to the image that holds the layer
karthik1729 Aug 29, 2026
7981423
Close before releasing, bound the evict close, and skip volumes in th…
karthik1729 Aug 29, 2026
b0869ca
Draft the persistent per-person home design
karthik1729 Aug 29, 2026
a9bbff9
Build the Azure object store concretely so it keeps its multipart view
karthik1729 Aug 29, 2026
3125abe
Release gateway tunnel slots exactly once and cap tunnels per pod
karthik1729 Aug 29, 2026
9e87b26
Put a ceiling on every merge worker git subprocess and job
karthik1729 Aug 29, 2026
741588c
Put every sshd SetEnv variable on the one line sshd reads
karthik1729 Aug 29, 2026
750011d
Build the SetEnv line outside the format call
karthik1729 Aug 29, 2026
1742f5a
Retry slow layer fetches and restarted stop pushes instead of parking
karthik1729 Aug 29, 2026
785e3bc
Put a button between the sign-in link and the session, and check the …
karthik1729 Aug 29, 2026
48c6f45
Judge upload sessions by last activity and stop rewriting unchanged m…
karthik1729 Aug 29, 2026
1225ba3
Pin every tier to the third audit-fix batch
karthik1729 Aug 29, 2026
e66d535
Reach every open change, record an exhausted merge-base as unknown, b…
karthik1729 Aug 29, 2026
b874eb1
Claim an unknown repo before any node opens it
karthik1729 Aug 29, 2026
4c5f69d
Drain before the stop push, honour bindings in claims, enforce quotas…
karthik1729 Aug 29, 2026
208602f
Make the agent's RBAC true, gate readiness on the leader, and stop bl…
karthik1729 Aug 29, 2026
5ee1144
Commit the lock file for the app crate's test dependencies
karthik1729 Aug 29, 2026
6a9737b
Count image pulls in memory and flush them off the GET path
karthik1729 Aug 29, 2026
2ee83ca
Bound the reachability checks on fetch and push to the change
karthik1729 Aug 29, 2026
e73d310
Stream git HTTP bodies instead of buffering whole packs
karthik1729 Aug 29, 2026
8dd623c
Pin every tier to the fourth audit-fix batch
karthik1729 Aug 29, 2026
a3d98c1
Serialise the git HTTP limit tests: the permit pool is process-global
karthik1729 Aug 29, 2026
8574da4
Pin every tier to the streamed git HTTP build
karthik1729 Aug 29, 2026
352e67a
Record the decision to stay on Flexible TLS for now
karthik1729 Aug 29, 2026
1e1ba7f
Consolidate a repo's packs online on the owning node
karthik1729 Aug 29, 2026
8a99288
Export Prometheus metrics and JSON logs from every binary
karthik1729 Aug 29, 2026
0ce9ab4
Gate every image on the test job and pin what CI leaves loose
karthik1729 Aug 29, 2026
988d9b5
Bump node from 22-bookworm-slim to 26-bookworm-slim in /web
dependabot[bot] Aug 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions .cargo/audit.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# rsa 0.9 (Marvin attack, RUSTSEC-2023-0071) reaches us only transitively through
# russh/ssh-key, and rsa has shipped no patched release — the fix lands in 0.10.
# Nothing here can be upgraded away, so the advisory would fail every CI run for a
# dependency we do not call directly.
# Revisit when `cargo tree -i rsa` shows 0.10 stable: drop this ignore, do not extend it.
[advisories]
ignore = ["RUSTSEC-2023-0071"]
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# The Dockerfile only COPYs compiled binaries out of target/<profile>/, so nothing else is context —
# not the source, and not the rest of target/ (gigabytes of rlibs and .d files).
*
!target/release/rustic-git
!target/release/rustic-git-api
!target/release/rustic-git-worker
!target/release/rustic-git-agent
!target/release/rustic-git-gateway
!target/dev-image/rustic-git
!target/dev-image/rustic-git-api
!target/dev-image/rustic-git-worker
!target/dev-image/rustic-git-agent
!target/dev-image/rustic-git-gateway
24 changes: 24 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Every action, base image and dependency in this repo is pinned by SHA or digest, which is only
# a virtue while something moves the pins. Weekly, grouped, so a Monday brings a handful of PRs
# rather than one per crate.
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule: { interval: weekly }
- package-ecosystem: docker
directory: /
schedule: { interval: weekly }
- package-ecosystem: docker
directory: /web
schedule: { interval: weekly }
- package-ecosystem: cargo
directory: /
schedule: { interval: weekly }
groups:
cargo: { patterns: ["*"] }
- package-ecosystem: npm
directory: /web
schedule: { interval: weekly }
groups:
npm: { patterns: ["*"] }
35 changes: 35 additions & 0 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Advisories arrive without a commit. `image.yml` runs cargo-deny only when master moves, and the
# web tree has no audit at all — this is the run that notices a CVE published on a quiet week.
# Red here means: bump the crate (`cargo update -p <crate>`) or the package (`bun update <pkg>`),
# or add a justified `ignore` to deny.toml, then let the normal push run confirm it.
name: audit
on:
schedule:
- cron: "0 6 * * 1" # weekly, Monday morning UTC
workflow_dispatch:

permissions:
contents: read

jobs:
cargo:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: EmbarkStudios/cargo-deny-action@b66acf5e9fe20f8aba065be86778a8a4c846f902 # v2
with:
command: check advisories
web:
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: web
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.3.14
- run: bun install --frozen-lockfile
- run: bun audit
20 changes: 20 additions & 0 deletions .github/workflows/cf-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Does the committed Cloudflare range list still match what Cloudflare publishes? A stale list
# fails safe on every copy (a new edge is refused, never wrongly trusted), which is exactly why
# nobody notices — this is the noticing. Red here means: run deploy/cf-sync.sh, commit, re-apply.
name: cf-sync
on:
schedule:
- cron: "17 6 * * 1" # weekly; Cloudflare's last change was 2024, so this is plenty
workflow_dispatch:
pull_request:
paths: ["deploy/cf-sync.sh", "deploy/k3s/cloudflare-ips-v4.txt", "deploy/ingress-nginx-*.yaml"]

permissions:
contents: read

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- run: deploy/cf-sync.sh
144 changes: 139 additions & 5 deletions .github/workflows/image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,163 @@ name: image
on:
push:
branches: [master]
# PRs get the test job only: a red commit is cheapest to catch before it is on master, and a
# PR has no business producing a package. `build` and `image` are skipped on this event.
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
test:
# GitHub's runner, not the self-hosted VM: that VM exists for its docker layer cache and
# carries no Rust toolchain. The cargo cache below keys on Cargo.lock, so after the first
# cold build (the C deps: aws-lc-sys, ring, zstd) this is a few minutes.
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
# audit-check posts its findings as a check run on the commit.
checks: write
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
with:
components: clippy
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
# Workspace-wide, not `--all-targets`: the test targets carry pre-existing lints that are not
# worth a reformat-sized diff (see CLAUDE.md). `cargo fmt --check` is deliberately absent
# for the same reason — the tree is not rustfmt-shaped and gating it means one repo-wide
# reformat commit, which is the owner's call, not CI's.
# `--locked` on both, like the Dockerfile and the build job: a stale lockfile must fail here,
# not pass here by rewriting Cargo.lock and then fail differently in `build`.
- run: cargo clippy --workspace --locked -- -D warnings
- run: cargo test --locked
- uses: rustsec/audit-check@69366f33c96575abad1ee0dba8212993eecbe998 # v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
# `audit-check` above covers advisories only. This adds the three checks a repo with this
# much crypto surface wants: banned/duplicate crates, licence policy, and source
# allowlisting. Config lives in deny.toml, next to Cargo.toml.
- uses: EmbarkStudios/cargo-deny-action@b66acf5e9fe20f8aba065be86778a8a4c846f902 # v2
with:
command: check

build:
# NOT `needs: test` — the compile and the tests run in parallel, and only `image` below waits
# for both. Waiting for tests before compiling added their whole duration (5m32s measured) to
# every image, serially, for nothing; gating the PUSH on them costs nothing extra.
#
# Compiled here, on the runner, NOT inside docker. cargo-chef under a `type=gha,mode=max` layer
# cache cached the dependency cook and nothing else: the workspace crates sat in the layer that
# also held the source, so every commit rebuilt them from scratch — 342 s of `cargo build` plus
# 114 s of cache export, per run. rust-cache keeps the whole target dir across commits, so an
# ordinary commit recompiles only the crates it touched.
#
# Inside rust:1-bookworm rather than on ubuntu-24.04 itself: the runtime images are
# bookworm-slim (glibc 2.36) and a binary linked against the runner's glibc 2.39 would not exec
# there. The step after the build checks that no newer symbol version crept in.
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 30
container: rust:1-bookworm@sha256:e70e2eec3d495fd5c8e0be74adda86507dfac7f51a724fbf9813ff59b2b247c7
permissions:
contents: read
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
# A red build that got through the C deps is still worth keeping.
cache-on-failure: true
- run: >
cargo build --release --locked
--bin rustic-git --bin rustic-git-api --bin rustic-git-worker
--bin rustic-git-agent --bin rustic-git-gateway
- name: glibc ceiling
run: |
set -eu
for b in rustic-git rustic-git-api rustic-git-worker rustic-git-agent rustic-git-gateway; do
need=$(objdump -T "target/release/$b" | grep -o 'GLIBC_[0-9.]*' | sort -uV | tail -1)
echo "$b needs $need"
if [ "$(printf '%s\nGLIBC_2.36\n' "$need" | sort -V | tail -1)" != GLIBC_2.36 ]; then
echo "::error::$b needs $need, bookworm-slim ships 2.36"; exit 1
fi
done
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: bins
path: |
target/release/rustic-git
target/release/rustic-git-api
target/release/rustic-git-worker
target/release/rustic-git-agent
target/release/rustic-git-gateway
if-no-files-found: error
retention-days: 1

image:
# Docker on the plain runner: buildx and the ghcr login have no business inside the rust
# container, and the artifact hop for five binaries is seconds.
#
# `needs: test` as well as `build`: a commit whose tests fail gets NO package — neither
# `:<sha>` nor `:latest`. The deploy side (`deploy/pin.sh`) can then treat "the tag exists"
# as "the tests passed", which is the only signal a repin from `git log` ever sees.
needs: [build, test]
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: bins
path: target/release
# upload-artifact drops the mode bits and the Dockerfile COPYs the files as they are.
- run: chmod +x target/release/rustic-git*
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
# Default docker-container driver: required for `type=gha` cache, which the classic
# `docker` driver cannot export to.
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
# Plain `type=gha`, no `mode=max`: the only layers worth caching now are the apt-get ones,
# and those are in the final images. `max` existed for the builder stage that is gone.
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
target: server
# linux/amd64 only: the cluster is amd64, and so are the binaries above.
platforms: linux/amd64
push: true
tags: |
ghcr.io/kloudlite/rustic-git:latest
ghcr.io/kloudlite/rustic-git:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
cache-to: type=gha
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
target: agent
platforms: linux/amd64
push: true
tags: |
ghcr.io/kloudlite/rustic-git-agent:latest
ghcr.io/kloudlite/rustic-git-agent:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
target: gateway
platforms: linux/amd64
push: true
tags: |
ghcr.io/kloudlite/rustic-git-gateway:latest
ghcr.io/kloudlite/rustic-git-gateway:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha
79 changes: 79 additions & 0 deletions .github/workflows/kl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: kl
on:
push:
tags: ["kl-v*"]
workflow_dispatch:

# The CLI ships on its own tags, not on master: `bins/kl` builds four host binaries for people's
# laptops, which has nothing to do with the cluster images `image.yml` pushes per commit.
permissions:
contents: read

jobs:
build:
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
# cross, because a glibc arm64 binary needs a matching sysroot the ubuntu runner has not
# got — the darwin pair build natively on macOS runners instead.
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
cross: true
- target: x86_64-apple-darwin
os: macos-latest
- target: aarch64-apple-darwin
os: macos-latest
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
# A fixed version: `cross` is a build tool that runs arbitrary containers, and an
# unpinned `cargo install` at release time is the one unpinned input in this file.
- if: matrix.cross
run: cargo install cross --version 0.2.5 --locked
- run: ${{ matrix.cross && 'cross' || 'cargo' }} build -p kl --release --locked --target ${{ matrix.target }}
- name: package
run: |
set -eu
name="kl-${{ matrix.target }}"
cp "target/${{ matrix.target }}/release/kl" "$name"
shasum -a 256 "$name" > "$name.sha256" 2>/dev/null || sha256sum "$name" > "$name.sha256"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: kl-${{ matrix.target }}
path: |
kl-${{ matrix.target }}
kl-${{ matrix.target }}.sha256

release:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
# For the provenance attestation below.
id-token: write
attestations: write
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
path: dist
merge-multiple: true
# One sha256sums file next to the assets: install.sh verifies against it.
- run: cd dist && cat *.sha256 > sha256sums && rm -f *.sha256
# `sha256sums` proves a download is intact; this proves it came from THIS workflow on THIS
# commit (`gh attestation verify kl-<target> -R kloudlite/rustic-git`). Free for a public
# repo, and the only origin signal `install.sh`'s same-origin checksum cannot give.
- uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3
with:
subject-path: dist/kl-*
- uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2
with:
files: dist/*
generate_release_notes: true
Loading
Loading