Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
843 commits
Select commit Hold shift + click to select a range
b3cbc0a
fix(overview): stop the node memory figure column eating slack
ericwang401 Jul 15, 2026
7cd4514
feat(ipam): give the IPAM tables mobile rows
ericwang401 Jul 15, 2026
8b1e320
docs: record the IPAM mobile-row session in the handoff
ericwang401 Jul 15, 2026
6c1e4c9
feat(backups): wire the quota display to real data
ericwang401 Jul 15, 2026
ae3ae3b
refactor: drop the Eloquent repository layer
ericwang401 Jul 15, 2026
fb003d2
refactor: move the Proxmox API clients to app/Services/Proxmox
ericwang401 Jul 15, 2026
376242c
docs: hand off the repository removal, backups quota, and verificatio…
ericwang401 Jul 15, 2026
9897d62
docs: record the backups quota browser verification
ericwang401 Jul 15, 2026
ffb505b
feat(backups): add a Create Backup dialog and wire the empty state
ericwang401 Jul 15, 2026
6acc227
docs(audit): tick the server subpage items and record the Base UI att…
ericwang401 Jul 15, 2026
5ef32b0
docs: hand off the Create Backup dialog
ericwang401 Jul 15, 2026
35fa06c
refactor(rebuild): put the Rebuild page on the shared width and rhythm
ericwang401 Jul 15, 2026
3235c73
refactor(radio): migrate the dormant RadioGroup to Base UI
ericwang401 Jul 15, 2026
5c9b7bb
refactor(ui): move Dialog/Drawer/Sheet to Base UI, replace Credenza
ericwang401 Jul 15, 2026
1a6f2f4
feat(dialog): scale a parent dialog back behind nested children
ericwang401 Jul 15, 2026
9a91060
docs: hand off the Base UI dialog migration and the modal-store plan
ericwang401 Jul 15, 2026
a4829b5
refactor(modals): rebuild the auth flow on real nested dialogs
ericwang401 Jul 15, 2026
8fa80f5
docs: record the nested-dialog modal refactor
ericwang401 Jul 15, 2026
362f4a2
docs: record the passkey-gate verification and the double-submit bug
ericwang401 Jul 15, 2026
573d025
fix(auth): stop the passkey gate running its ceremony twice
ericwang401 Jul 15, 2026
4897b64
docs: record the double-ceremony fix
ericwang401 Jul 15, 2026
87a22d7
docs: record the authenticator step-dialog verification
ericwang401 Jul 15, 2026
50338ff
docs(audit): tick the textarea dialog browser-check
ericwang401 Jul 15, 2026
6c75572
docs(audit): close out the definition-of-done criteria
ericwang401 Jul 15, 2026
50a0d3a
docs: record the audit close-out state
ericwang401 Jul 15, 2026
9fafaaf
fix(storages): make the storage_to_node pivot insertable on Postgres
ericwang401 Jul 15, 2026
2015b03
docs: record the live-node findings and the pivot bug
ericwang401 Jul 15, 2026
ce6d63a
docs: close the live disks verification
ericwang401 Jul 15, 2026
a25aeb6
fix(ui): add retryable collection error states
ericwang401 Jul 15, 2026
f52872f
fix(storages): make deletion persistent
ericwang401 Jul 15, 2026
4246423
fix(servers): unblock deferred creation
ericwang401 Jul 15, 2026
0d5dcdc
fix(backups): persist requested lock
ericwang401 Jul 15, 2026
16eb702
docs: close graphs browser verification
ericwang401 Jul 15, 2026
b84f7a6
docs: close token UI verification
ericwang401 Jul 15, 2026
d028ef7
feat(tokens): restrict application tokens by network
ericwang401 Jul 15, 2026
04798cf
fix(dialog): stop dialogs mounting as drawers, migrate to nova
ericwang401 Jul 15, 2026
ff8bacb
fix(account): require confirmed identity to mint API and SSH keys
ericwang401 Jul 15, 2026
f2e1df1
fix(passkeys): stop the dev origin override rejecting every registration
ericwang401 Jul 15, 2026
4db300c
fix(2fa): confirm the TOTP code before two factor counts as enabled
ericwang401 Jul 15, 2026
e7db2ff
fix(2fa): stop setup handing out a QR for a discarded secret
ericwang401 Jul 15, 2026
c526286
docs: hand off the nested-dialog peek and the auth overhaul
ericwang401 Jul 16, 2026
7710312
feat(auth): add unified second-factor challenge and recovery codes
ericwang401 Jul 16, 2026
edd1e57
feat(account): give recovery codes one home, off the authenticator
ericwang401 Jul 16, 2026
c46ab54
refactor(modals): type modal data per family, add useModal/useOpenModal
ericwang401 Jul 16, 2026
8959513
fix(passkeys): make every WebAuthn challenge single use
ericwang401 Jul 16, 2026
f176086
fix(query): stop retrying 4xx responses
ericwang401 Jul 16, 2026
43fb51d
fix(modals): reset a modal family when its last modal unmounts
ericwang401 Jul 16, 2026
cddf08c
fix(auth): let the server own whether identity is confirmed
ericwang401 Jul 16, 2026
cf5bc9e
fix(card): let card content fill a stretched card
ericwang401 Jul 16, 2026
798fef4
fix(ddev): pin the postgres host port
ericwang401 Jul 16, 2026
1809112
fix(dialog): stop one long string widening the popup
ericwang401 Jul 16, 2026
b687e19
docs(card-design): document the dialog grid blowout
ericwang401 Jul 16, 2026
00fe3fc
feat(auth): make a password change evict the attacker
ericwang401 Jul 16, 2026
80f4783
style: apply the pint laravel preset repo-wide
ericwang401 Jul 16, 2026
f8caf88
docs: drop the auth handoff's stale outstanding list
ericwang401 Jul 16, 2026
edfa75a
fix(forms): stop a boolean field latching itself uncontrolled
ericwang401 Jul 16, 2026
852a50b
fix(data-table): float the selection bar, stop the select column bloa…
ericwang401 Jul 17, 2026
3c4a3ba
feat(nodes): say why a node is unreachable, where it went wrong
ericwang401 Jul 17, 2026
da028fa
feat(nodes): poll node reachability instead of asking on every render
ericwang401 Jul 17, 2026
260462d
docs: hand off the admin UI pass and node status work
ericwang401 Jul 17, 2026
f587f04
fix(nodes): stop pairing a two-field card with a six-field one
ericwang401 Jul 17, 2026
11f9358
fix(servers): make the overview stat row read as one design
ericwang401 Jul 17, 2026
c245a12
fix(servers): stop the overview rows going 4-up before they fit
ericwang401 Jul 17, 2026
41b2775
docs: re-point the handoff's SHAs at the rebased history
ericwang401 Jul 17, 2026
ef1632f
fix(servers): stop the live tiles claiming to load forever
ericwang401 Jul 17, 2026
90f70d9
feat(nodes): record guest power state from the poll that was already …
ericwang401 Jul 17, 2026
743c8b2
feat(servers): show guest power state in the client server list
ericwang401 Jul 17, 2026
4a76193
docs: record slice 2 as built, and where it departed from the plan
ericwang401 Jul 17, 2026
0d7fa2b
feat(servers): rail the power state down the row, and make the whole …
ericwang401 Jul 17, 2026
b9049d3
feat: replace Coterm with Anchor control plane
ericwang401 Jul 17, 2026
15c6161
feat: add Anchor administration UI
ericwang401 Jul 17, 2026
d39272d
feat: add custom Anchor console UI
ericwang401 Jul 17, 2026
dfa5c0d
refactor(deployments): give each step a single guarded owner
ericwang401 Jul 17, 2026
0134062
fix(typescript): resolve transformer reference warnings
ericwang401 Jul 17, 2026
1ee7e47
feat(nodes): test saved connection settings
ericwang401 Jul 22, 2026
ca69407
feat(servers): show power state in admin lists
ericwang401 Jul 22, 2026
6700792
feat(nodes): show polled resources on dashboard
ericwang401 Jul 22, 2026
135a0bd
refactor(nodes): share connection error vocabulary
ericwang401 Jul 22, 2026
ef0de83
fix(auth): restore static analysis against current packages
ericwang401 Jul 22, 2026
ee48194
ci: gate and package deployable releases
ericwang401 Jul 22, 2026
b3952fe
fix(ci): build route tree before release typecheck
ericwang401 Jul 22, 2026
9e2d6a1
fix(account): keep the keychain card level with its grid row-mate
ericwang401 Jul 24, 2026
aff13c5
fix(account): stop the SSH key row buckling in a narrow card
ericwang401 Jul 24, 2026
7560e70
refactor(ui): standardize buttons on the default h-8 size
ericwang401 Jul 24, 2026
745ffd7
refactor(nodes): give network interface rows icon + badges
ericwang401 Jul 24, 2026
eff72f5
feat(ipam): distinguish system and operator address reservations
ericwang401 Jul 24, 2026
86c7358
fix(account): stop the authenticator dialog resizing when the QR loads
ericwang401 Jul 24, 2026
37f15c7
chore: ignore the local auto-memory directory
ericwang401 Jul 24, 2026
72f5d91
refactor(nodes): share form sections between create and settings
ericwang401 Jul 24, 2026
7fe7fa0
fix(sandbox): make ddev and headless browsing work out of the box
ericwang401 Jul 24, 2026
3a5e0ef
fix(nodes): mark the form dirty when a connection test fills capacity
ericwang401 Jul 25, 2026
656bc57
fix(ui): stop a tooltip trigger submitting the form around it
ericwang401 Jul 25, 2026
513648a
fix(ipam): reserve system addresses at unit granularity
ericwang401 Jul 25, 2026
d70b41d
chore(sbx): drop the repo-local tailscale kit
ericwang401 Jul 27, 2026
326d285
fix(sbx): update broken command list
ericwang401 Jul 31, 2026
5285a9a
feat(nodes): add VLAN registry and network topology view
ericwang401 Jul 31, 2026
bd9fc58
feat(anchor): probe stale Anchors for liveness
ericwang401 Jul 31, 2026
d2a9a1c
refactor(power): track power actions by Proxmox task UPID
ericwang401 Jul 31, 2026
af4db6a
fix(console): stop the reconnect loop from an unstable mutation hook
ericwang401 Jul 31, 2026
161da50
feat(overview): distinguish unavailable node metrics from zero
ericwang401 Jul 31, 2026
861fa29
feat(power): surface power action progress and outcome in the UI
ericwang401 Jul 31, 2026
12c3868
fix(power): keep the server list's power state fresh after an action
ericwang401 Jul 31, 2026
af7e453
feat(ipam): redesign server address list as address panels
ericwang401 Jul 31, 2026
78e54cf
refactor(ipam): derive an address block's version from its base IP
ericwang401 Jul 31, 2026
000fca1
fix(servers): record the allocated addresses as the server's primaries
ericwang401 Jul 31, 2026
c0ac472
refactor(servers): name the condition axes and split suspension from …
ericwang401 Jul 31, 2026
2854182
feat(ui): make the overflow sheet's edge fade track scroll position
ericwang401 Jul 31, 2026
de099a8
fix(account): carry the identity gate into key removal
ericwang401 Jul 31, 2026
d5961d4
feat(overview): give each client server row its own card surface
ericwang401 Jul 31, 2026
528a631
refactor(ui): replace sonner with shadcn's Base UI toast
ericwang401 Jul 31, 2026
5eceb16
fix(servers): wrap the statistics response like its sibling endpoints
ericwang401 Aug 1, 2026
840a43b
feat(graphs): rebuild resource usage as one synchronised panel
ericwang401 Aug 1, 2026
c8ce3a7
fix(graphs): name both directions in the disk and network rails
ericwang401 Aug 1, 2026
bbbac6e
fix(graphs): give the rail a value column and sit the age on the name…
ericwang401 Aug 1, 2026
802da93
fix(graphs): stop the rail legends sliding when their placeholder res…
ericwang401 Aug 1, 2026
6d26b04
feat(overview): put a live trend under the CPU and memory figures
ericwang401 Aug 1, 2026
fed0e78
fix(overview): lay the trend over the tile instead of extending it
ericwang401 Aug 1, 2026
6986116
refactor(servers): collect live telemetry once per server, not per co…
ericwang401 Aug 1, 2026
1d62d48
fix(ui): slide the active tab slab between tabs
ericwang401 Aug 1, 2026
004394a
fix(graphs): keep the live feed out of the chart subtree
ericwang401 Aug 1, 2026
4c028ca
feat(servers): provision the serial device the terminal console needs
ericwang401 Aug 2, 2026
cca5ab1
feat(console): rebuild the console button and its picker
ericwang401 Aug 2, 2026
9c3d12f
feat(console): say why a console failed, and stop hiding the guest
ericwang401 Aug 2, 2026
4a60e5a
feat(anchor): let Anchors reach the panel at a different URL
ericwang401 Aug 2, 2026
af48a6b
fix(anchor): recompute compatibility after the liveness probe
ericwang401 Aug 2, 2026
ae0602d
docs(agents): require arrow functions in the frontend
ericwang401 Aug 2, 2026
5ca2c21
fix(overview): give the lifecycle card one rhythm and one rule
ericwang401 Aug 9, 2026
a6281fd
fix(branding): stop shipping Laravel's mark as the favicon
ericwang401 Aug 12, 2026
1df179b
fix(branding): resolve the favicon from the app root, not the route
ericwang401 Aug 12, 2026
1d4b8ac
style: remove live resource pulsing icon
ericwang401 Aug 12, 2026
4bc40a2
style(graphs): drop the accent stripes from the metric rail
ericwang401 Aug 16, 2026
fa5321c
chore(graphs): delete the orphaned LiveIndicator
ericwang401 Aug 16, 2026
2d7a534
fix(backups): stop password managers autofilling the backup name
ericwang401 Aug 16, 2026
8371aa5
feat(rebuild): rebuild the server rebuild and install-progress screens
ericwang401 Aug 16, 2026
df5e71c
docs(card-design): record what the rebuild screens settled
ericwang401 Aug 16, 2026
0fd5039
fix(storage): stop the boot order arriving double-wrapped
ericwang401 Aug 16, 2026
f14dba8
feat(passkeys): name new passkeys after the authenticator that made them
ericwang401 Aug 16, 2026
03d007a
fix(servers): stop the network sync overwriting the firewall policy
ericwang401 Aug 16, 2026
56e3625
feat(servers): expose the Proxmox firewall over the client API
ericwang401 Aug 16, 2026
a8f0dbc
feat(servers): build the Firewall tab
ericwang401 Aug 16, 2026
cad7bb9
fix(nodes): soften the sticky form bar's edge
ericwang401 Aug 16, 2026
05053ac
fix(console): say why the display console failed, and offer the fix
ericwang401 Aug 16, 2026
40bd356
feat(servers): make the address list a table that stops growing
ericwang401 Aug 17, 2026
fc25732
fix(ui): let the button spinner replace the icon it stands in for
ericwang401 Aug 17, 2026
47d8dee
fix(ui): make a checked switch look checked in dark mode
ericwang401 Aug 17, 2026
ff0410f
fix(ui): stop dialogs clipping their own content
ericwang401 Aug 17, 2026
484d400
feat(servers): rebuild the firewall tab as a rule ledger
ericwang401 Aug 17, 2026
05d7ccf
feat(servers): rebuild the storage tab around one list of devices
ericwang401 Aug 17, 2026
b87aaa2
feat(servers): let admins hop between a server's client and admin views
ericwang401 Aug 17, 2026
283b45e
style(rebuild): shorten OS card description
ericwang401 Aug 17, 2026
2d91609
feat(servers): let admins copy a server's IDs from the details card
ericwang401 Aug 17, 2026
2f0cb98
fix(ui): make Button's asChild work and let menus size to their items
ericwang401 Aug 17, 2026
f8712dd
test(servers): cover what the storage endpoint narrows a device down to
ericwang401 Aug 17, 2026
7fdc08d
fix(servers): make a dragged firewall rule land where it is dropped
ericwang401 Aug 17, 2026
0cfbd3c
fix(overview): stop the KPI sparklines reacting to hover
ericwang401 Aug 17, 2026
fbaf089
feat(nodes): show total datastore usage per node on the admin dashboard
ericwang401 Aug 17, 2026
ac76d05
feat(admin): tell operators when a newer release is out
ericwang401 Aug 17, 2026
c3cf334
test: share the root-admin helper instead of declaring it twice
ericwang401 Aug 17, 2026
fa8890e
feat(storages): record what Proxmox says about each registered storage
ericwang401 Aug 17, 2026
879407d
feat(storages): show recorded capacity when a node is unreachable
ericwang401 Aug 17, 2026
63c3526
feat(storages): put capacity on the row instead of behind a modal
ericwang401 Aug 17, 2026
cdc79e3
fix(nodes): stop polling a node the poller already knows is down
ericwang401 Aug 17, 2026
7fcda86
fix(storages): scope every pivot write to the node it was made on
ericwang401 Aug 17, 2026
7d9eafd
feat(nodes): record which PVE cluster a node belongs to
ericwang401 Aug 17, 2026
6bc2b71
feat(storages): let one storage be attached to several nodes
ericwang401 Aug 17, 2026
afb2332
feat(storages): offer the cluster's storages to a node that lacks them
ericwang401 Aug 17, 2026
d345c4d
feat(storages): name the other nodes a shared pool reaches
ericwang401 Aug 17, 2026
c79768c
docs(nodes): record the storage model and cluster work in the plan
ericwang401 Aug 17, 2026
23c9b74
feat(storages): add a fleet-wide storage inventory
ericwang401 Aug 17, 2026
0fcc6bb
feat(nodes): say whether a node is in a Proxmox cluster
ericwang401 Aug 17, 2026
fa8e939
docs(nodes): record that the global storage list shipped
ericwang401 Aug 17, 2026
6f24c69
refactor(storages): drop is_shareable in favour of what Proxmox reports
ericwang401 Aug 17, 2026
dd165e8
fix(overview): count fleet storage from what the poll observed
ericwang401 Aug 17, 2026
7c73017
style(storages): drop the list counters and move actions under the he…
ericwang401 Aug 17, 2026
71fa441
feat(storages): let Proxmox decide which nodes reach a shared pool
ericwang401 Aug 17, 2026
5e0aeb1
feat(storages): register storage by picking it from Proxmox
ericwang401 Aug 17, 2026
5a84af4
fix(storages): give the add-storage dialog real empty states
ericwang401 Aug 17, 2026
809f016
test(nodes): stop the shared-pool link test collating by luck
ericwang401 Aug 17, 2026
f79be30
fix(jobs): stop a killed worker from wedging a server forever
ericwang401 Aug 17, 2026
4d09890
test(jobs): catch constructor changes that strand queued payloads
ericwang401 Aug 17, 2026
ea7f194
feat(servers): save a build as a preset and apply it in one pick
ericwang401 Aug 19, 2026
02a93af
refactor(servers): ask the create form only what a build authors
ericwang401 Aug 19, 2026
df2a184
fix(anchors): let the panel-URL settings migration run a second time
ericwang401 Aug 19, 2026
9f083bb
fix(config): give maintenance mode a store Convoy actually has
ericwang401 Aug 19, 2026
083a4d5
refactor(config): cut .env.example to what an install must set
ericwang401 Aug 19, 2026
88ed88e
fix(release): stop the archive step listing a file that does not exist
ericwang401 Aug 19, 2026
ada1fff
feat(deploy): ship Convoy as a container image with a one-command ins…
ericwang401 Aug 19, 2026
f38e9bb
fix(deploy): mark the deployment scripts executable
ericwang401 Aug 19, 2026
96d76a3
fix(ui): give focus rings room inside disclosure panels
ericwang401 Aug 19, 2026
ab5e5f7
fix(ui): let a confirmation's button keep its own variant
ericwang401 Aug 19, 2026
febfae3
feat(anchors): rebuild the admin resource as a roster and a detail page
ericwang401 Aug 19, 2026
1b9a81c
feat(anchors): rotate the installation secret on every enrollment
ericwang401 Aug 19, 2026
fbd0f43
feat(storages): explain the Proxmox backend on hover instead of renam…
ericwang401 Aug 19, 2026
03b0e92
feat(storages): expose what is occupying a storage, and let an admin …
ericwang401 Aug 19, 2026
c929d58
feat(storages): a page for what is filling a storage, and buttons to …
ericwang401 Aug 19, 2026
1458374
fix(storages): send the node's list to the storage page, not a dialog
ericwang401 Aug 19, 2026
6f96acd
feat(audit): record what happens in the panel, and show it
ericwang401 Aug 20, 2026
75a905c
refactor(storages): let Proxmox decide what a storage may hold
ericwang401 Aug 20, 2026
1ac1c39
fix(servers): say -1 for unmetered, instead of leaving the field blank
ericwang401 Aug 20, 2026
d9a8ed4
fix(sbx): stop sandbox certs from breaking HTTPS on the host
ericwang401 Aug 20, 2026
514629b
feat(clusters): identify clusters by their CA, and file storages once…
ericwang401 Aug 20, 2026
ca1590c
chore(templates): shelve the import feature until Cofoundry publishes…
ericwang401 Aug 20, 2026
409d71b
docs: retire the handoffs whose work has shipped
ericwang401 Aug 20, 2026
86367c5
feat(backups): fold the quota into the backups view and gate creation…
ericwang401 Aug 20, 2026
50e17e6
style(firewall): tidy the log card markup
ericwang401 Aug 20, 2026
b88158d
feat(servers): confirm identity before setting a root password
ericwang401 Aug 20, 2026
f7c05f0
docs: remove excalidraw document
ericwang401 Aug 20, 2026
73d4c36
feat(servers): follow guests that PVE moves between nodes
ericwang401 Aug 20, 2026
342d6bf
fix: make avatar menu's spacing consistent
ericwang401 Aug 20, 2026
314ce0d
feat(users): manage panel accounts from the admin side
ericwang401 Aug 20, 2026
a06cb9f
fix(ui): make disabled checkboxes, radios and switches look disabled
ericwang401 Aug 20, 2026
e1eaa0e
feat(anchors): mint enrollment keys that admit new installations
ericwang401 Aug 20, 2026
3b55f35
feat(anchors): let a machine enroll itself, and hold it until approved
ericwang401 Aug 21, 2026
5007cbb
refactor(anchors): a node and its agent stop being two records
ericwang401 Aug 22, 2026
1362ac5
feat(anchors): approval asks one question instead of showing a form
ericwang401 Aug 22, 2026
c555391
refactor(nodes): registering a host by hand stops being an option
ericwang401 Sep 7, 2026
039e0f5
refactor(ui): stop narrating the panel in page and card descriptions
ericwang401 Sep 7, 2026
07d6ab1
refactor(ui): the nodes card says less about the nodes that are fine
ericwang401 Sep 7, 2026
2e141c9
refactor(ui): page actions stop sharing the heading's row
ericwang401 Sep 7, 2026
510e111
feat(images): build servers by importing a disk image, not cloning a …
ericwang401 Sep 7, 2026
b7a144c
refactor(storages): the free-space line stops being typeset as output
ericwang401 Sep 7, 2026
84f070e
refactor(anchors): the enroll page stops narrating the install command
ericwang401 Sep 7, 2026
968ee43
feat(panel): account profiles, credential review, IPAM capacity, ISO …
ericwang401 Sep 7, 2026
0f16990
fix(ipam): drop the duplicate summary and bulk route registrations
ericwang401 Sep 7, 2026
2057057
refactor(auth): the sign-in screens go back to stock nova components
ericwang401 Sep 7, 2026
12d0a6b
refactor(servers): the state tile says running with a shape, not a pulse
ericwang401 Sep 7, 2026
3989710
fix(models): a saving listener on a subclass never ran
ericwang401 Sep 7, 2026
4802e65
refactor(updates): the version card labels itself instead of narrating
ericwang401 Sep 7, 2026
88ad2a8
feat(account): profile settings move into the sidebar, and pictures g…
ericwang401 Sep 7, 2026
261dd7d
refine(settings): the account policy screen says who it governs
ericwang401 Sep 7, 2026
4a4b3c0
refactor(networking): the address cards are the frame, not a box arou…
ericwang401 Sep 7, 2026
efa7085
feat(ipam): a block draws its address space instead of paginating it
ericwang401 Sep 7, 2026
fb46218
feat(ipam): assignment starts from the server, and the map finishes t…
ericwang401 Sep 7, 2026
a23ad59
fix(ipam): the map's selections reach the server, and the page believ…
ericwang401 Sep 7, 2026
c6ad472
fix(ipam): the utilisation column fits, and generating redraws the grid
ericwang401 Sep 7, 2026
6740ddc
fix(ipam): the block table stops competing with itself for width
ericwang401 Sep 7, 2026
fc251d7
feat(mail): the panel's emails are built from its own design tokens
ericwang401 Sep 7, 2026
33d97ba
feat(account): the operator can lock the profile picture too
ericwang401 Sep 7, 2026
6d48c22
feat(mail): the panel configures its own SMTP, and can prove it works
ericwang401 Sep 7, 2026
b302f7e
feat(users): a new account is invited to set its own password
ericwang401 Sep 7, 2026
280c71b
chore(issues): move the templates onto issue types and current facts
ericwang401 Sep 7, 2026
524146f
docs(templates): drop the reference to a commit that no longer exists
ericwang401 Sep 7, 2026
3ef53e3
Merge branch 'main' into next
ericwang401 Sep 8, 2026
c2c1384
docs(changelog): note that the v4.6.1 ISO fix describes the 4.x model
ericwang401 Sep 8, 2026
f470261
ci(docker): name branch builds after the branch, and assign latest ou…
ericwang401 Sep 8, 2026
34990cc
docs(readme): point the CI badge at a branch that exists, drop FOSSA …
ericwang401 Sep 8, 2026
d260719
chore: rename the v10 working title to v5 across the tree
ericwang401 Sep 8, 2026
6ac8e8a
chore: drop branch references the reorganization left dangling
ericwang401 Sep 8, 2026
0a7e368
ci: drop the 4.x trigger that could never fire from this branch
ericwang401 Sep 8, 2026
ce3ebd2
ci: trigger only on main, ahead of retiring next
ericwang401 Sep 8, 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
  •  
  •  
  •  
38 changes: 38 additions & 0 deletions .ddev/addon-metadata/redis/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: redis
repository: ddev/ddev-redis
version: v2.2.0
install_date: "2026-07-04T11:24:16-04:00"
project_files:
- docker-compose.redis.yaml
- redis/scripts/settings.ddev.redis.php
- redis/scripts/setup-drupal-settings.sh
- redis/scripts/setup-redis-optimized-config.sh
- redis/redis.conf
- redis/advanced.conf
- redis/append.conf
- redis/general.conf
- redis/io.conf
- redis/memory.conf
- redis/network.conf
- redis/security.conf
- redis/snapshots.conf
- commands/host/redis-backend
- commands/redis/redis-cli
- commands/redis/redis-flush
global_files: []
removal_actions:
- |
#ddev-description:Remove redis settings if applicable
files=(
"${DDEV_APPROOT}/${DDEV_DOCROOT}/sites/default/settings.ddev.redis.php"
"${DDEV_APPROOT}/.ddev/docker-compose.redis_extra.yaml"
)
for file in "${files[@]}"; do
if [ -f "$file" ]; then
if grep -q '#ddev-generated' "$file"; then
rm -f "$file"
else
echo "Unwilling to remove '$file' because it does not have #ddev-generated in it; you can manually delete it if it is safe to delete."
fi
fi
done
124 changes: 124 additions & 0 deletions .ddev/commands/host/redis-backend
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/env bash
#ddev-generated

## Description: Use a different key-value store for Redis
## Usage: redis-backend <image> [optimize]
## Example: ddev redis-backend redis-alpine optimize

REDIS_DOCKER_IMAGE=${1:-}
REDIS_CONFIG=${2:-}
NAME=$REDIS_DOCKER_IMAGE

function show_help() {
cat <<EOF
Usage: ddev redis-backend <image|alias> [optimize]

Choose from predefined aliases, or provide any Redis-compatible Docker image.
Note that not every Docker image can work right away, and you may need to override
the "command:" in the docker-compose.redis_extra.yaml file

Available aliases:
redis redis:7
redis-alpine redis:7-alpine
valkey valkey/valkey:8
valkey-alpine valkey/valkey:8-alpine

Custom backend:
You can specify any Docker image, e.g.:
ddev redis-backend redis:6

Optional:
optimize Apply additional Redis configuration with resource limits
optimized Same as optimize

Examples:
ddev redis-backend redis-alpine optimize
ddev redis-backend valkey
ddev redis-backend redis:7.2-alpine
EOF
exit 0
}

function optimize_config() {
[[ "$REDIS_CONFIG" != "optimized" && "$REDIS_CONFIG" != "optimize" ]] && return
ddev dotenv set .ddev/.env.redis --redis-optimized=true
}

function change_hostname() {
[[ "${REDIS_HOSTNAME:-}" == "" ]] && return
ddev dotenv set .ddev/.env.redis --redis-hostname="$REDIS_HOSTNAME"
}

function cleanup() {
rm -f "$DDEV_APPROOT/.ddev/.env.redis"
rm -rf "$DDEV_APPROOT/.ddev/redis/"
rm -f "$DDEV_APPROOT/.ddev/docker-compose.redis.yaml" "$DDEV_APPROOT/.ddev/docker-compose.redis_extra.yaml"

redis_volume="ddev-$(ddev status -j | docker run -i --rm ddev/ddev-utilities jq -r '.raw.name')_redis"
if docker volume ls -q | grep -qw "$redis_volume"; then
ddev stop
docker volume rm "$redis_volume"
fi
}

function check_docker_image() {
echo "Pulling ${REDIS_DOCKER_IMAGE}..."
if ! docker pull "$REDIS_DOCKER_IMAGE"; then
echo >&2 "❌ Unable to pull ${REDIS_DOCKER_IMAGE}"
exit 2
fi
}

function use_docker_image() {
[[ "$REDIS_DOCKER_IMAGE" != "redis:7" ]] && ddev dotenv set .ddev/.env.redis --redis-docker-image="$REDIS_DOCKER_IMAGE"
REPO=$(ddev add-on list --installed -j 2>/dev/null | docker run -i --rm ddev/ddev-utilities jq -r '.raw[] | select(.Name=="redis") | .Repository // empty' 2>/dev/null)
ddev add-on get "${REPO:-ddev/ddev-redis}"
}

case "$REDIS_DOCKER_IMAGE" in
redis)
NAME="Redis 7"
REDIS_DOCKER_IMAGE="redis:7"
;;
redis-alpine)
NAME="Redis 7 Alpine"
REDIS_DOCKER_IMAGE="redis:7-alpine"
;;
valkey)
NAME="Valkey 8"
REDIS_DOCKER_IMAGE="valkey/valkey:8"
REDIS_HOSTNAME="valkey"
;;
valkey-alpine)
NAME="Valkey 8 Alpine"
REDIS_DOCKER_IMAGE="valkey/valkey:8-alpine"
REDIS_HOSTNAME="valkey"
;;
""|--help|-h)
show_help
;;
*)
NAME="$REDIS_DOCKER_IMAGE"
# Allow unknown image, nothing to override
;;
esac

check_docker_image
cleanup
optimize_config
change_hostname
use_docker_image

echo
echo "✅ Redis backend: $REDIS_DOCKER_IMAGE"
if [[ "$REDIS_CONFIG" == "optimized" || "$REDIS_CONFIG" == "optimize" ]]; then
echo "⚙️ Redis config: optimized"
else
echo "⚙️ Redis config: default"
fi

echo
echo "📝 Commit the '.ddev' directory to version control"

echo
echo "🔄 Redis config available after 'ddev restart'"
13 changes: 13 additions & 0 deletions .ddev/commands/redis/redis-cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env sh

#ddev-generated
## Description: Run redis-cli inside the Redis container
## Usage: redis-cli [flags] [args]
## Example: "ddev redis-cli KEYS *" or "ddev redis-cli INFO" or "ddev redis-cli --version"
## Aliases: redis

if [ -f /etc/redis/conf/security.conf ]; then
redis-cli -p 6379 -h "${REDIS_HOSTNAME:-redis}" -a redis --no-auth-warning $@
else
redis-cli -p 6379 -h "${REDIS_HOSTNAME:-redis}" $@
fi
12 changes: 12 additions & 0 deletions .ddev/commands/redis/redis-flush
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env sh

#ddev-generated
## Description: Flush all cache inside the Redis container
## Usage: redis-flush
## Example: "ddev redis-flush"

if [ -f /etc/redis/conf/security.conf ]; then
redis-cli -p 6379 -h "${REDIS_HOSTNAME:-redis}" -a redis --no-auth-warning FLUSHALL ASYNC
else
redis-cli -p 6379 -h "${REDIS_HOSTNAME:-redis}" FLUSHALL ASYNC
fi
75 changes: 75 additions & 0 deletions .ddev/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: convoy
type: laravel
docroot: public
php_version: "8.4"
webserver_type: nginx-fpm

database:
type: postgres
version: "17"

# Without this DDEV assigns a random ephemeral host port on every start, which
# breaks saved connections in GUI clients (TablePlus, DataGrip, psql aliases).
host_db_port: "5432"

nodejs_version: "22"
corepack_enable: false

# ext-gmp is required by composer.json (prod Dockerfile installs it too).
webimage_extra_packages:
- php8.4-gmp

# Postgres + redis + mail overrides. These are real container env vars, so they
# take precedence over .env (Laravel's Dotenv does not overwrite existing env).
web_environment:
- APP_URL=https://convoy.ddev.site
- DB_CONNECTION=pgsql
- DB_HOST=db
- DB_PORT=5432
- DB_DATABASE=db
- DB_TEST_DATABASE=db_test
- DB_USERNAME=db
- DB_PASSWORD=db
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=
- CACHE_STORE=redis
- QUEUE_CONNECTION=redis
- SESSION_DRIVER=redis
- MAIL_MAILER=smtp
- MAIL_HOST=localhost
- MAIL_PORT=1025

# The test suite (RefreshDatabase) runs against a separate `db_test` database so
# its migrate:fresh / sequence churn never touches dev data. Postgres has no
# CREATE DATABASE IF NOT EXISTS, so createdb is guarded to stay idempotent.
hooks:
post-start:
# Pin `db` in /etc/hosts to the real db container. Some Docker-sandbox setups
# give the web container a resolver with a search domain + ndots:0, so a bare
# `db` lookup can fall through to the sandbox host's wildcard DNS (which answers
# `db.<sandbox>.docker.internal` with an unrelated host-network Postgres) — and
# then PHP-FPM and `ddev exec` end up on DIFFERENT databases with the same
# DB_HOST (see docs/v5-next-handoff.md). This fix is sandbox-agnostic: `getent
# hosts db` gets the real container IP from docker's embedded DNS (authoritative
# for the service name), and pinning it in /etc/hosts makes nsswitch `files`
# win over DNS, closing the hole. A no-op where there's no collision. Re-run
# every start so it survives the container IP drifting.
- exec: "sudo bash -c 'H=$(getent hosts db | head -n1 | sed \"s/[[:space:]].*//\"); grep -qw db /etc/hosts || echo \"$H db\" >> /etc/hosts'"
- exec: "PGPASSWORD=db createdb -h db -U db db_test 2>/dev/null || true"

# Replaces the compose `horizon` and `scheduler` services.
web_extra_daemons:
- name: horizon
command: "php artisan horizon"
directory: /var/www/html
- name: scheduler
command: "php artisan schedule:work"
directory: /var/www/html

# Expose the Vite dev server.
web_extra_exposed_ports:
- name: vite
container_port: 3000
http_port: 3011
https_port: 3000
27 changes: 27 additions & 0 deletions .ddev/docker-compose.redis.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ddev-generated
services:
redis:
container_name: ddev-${DDEV_SITENAME}-redis
image: ${REDIS_DOCKER_IMAGE:-redis:7}
hostname: ${REDIS_HOSTNAME:-redis}
# These labels ensure this service is discoverable by ddev.
labels:
com.ddev.site-name: ${DDEV_SITENAME}
com.ddev.approot: ${DDEV_APPROOT}
restart: "no"
expose:
- 6379
volumes:
- ".:/mnt/ddev_config"
- "ddev-global-cache:/mnt/ddev-global-cache"
- "./redis:/etc/redis/conf"
- "redis:/data"
command: /etc/redis/conf/redis.conf
x-ddev:
describe-url-port: |
Backend: ${REDIS_DOCKER_IMAGE:-redis:7}
describe-info: |
Pass: <none>

volumes:
redis:
23 changes: 23 additions & 0 deletions .ddev/docker-compose.victoriametrics.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
services:
victoriametrics:
container_name: ddev-${DDEV_SITENAME}-victoriametrics
image: victoriametrics/victoria-metrics:v1.115.0
hostname: victoriametrics
# These labels ensure this service is discoverable by ddev.
labels:
com.ddev.site-name: ${DDEV_SITENAME}
com.ddev.approot: ${DDEV_APPROOT}
restart: "no"
expose:
- 8428
command:
- "-retentionPeriod=90d"
- "-storageDataPath=/victoria-metrics-data"
volumes:
- "victoriametrics:/victoria-metrics-data"
x-ddev:
describe-info: |
VictoriaMetrics: http://victoriametrics:8428

volumes:
victoriametrics:
13 changes: 13 additions & 0 deletions .ddev/redis/redis.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Redis configuration.
# #ddev-generated
# Example configuration files for reference:
# http://download.redis.io/redis-stable/redis.conf
# http://download.redis.io/redis-stable/sentinel.conf

maxmemory 2048mb
maxmemory-policy allkeys-lfu

# to disable Redis persistence, remove ddev-generated from this file,
# and uncomment the two lines below:
#appendonly no
#save ""
62 changes: 62 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Build context excludes. Keep this tight: the image build copies the whole
# tree, and docs/pve-api alone is tens of megabytes of generated API reference
# that has no business in a runtime image.

.git
.github
.ddev
.idea
.vscode
.claude
.sbx
.tanstack
.tinker

# Installed fresh inside the build so the image never inherits a host-built tree.
node_modules
vendor

# Generated during the build (and gitignored), never copied in.
public/build
public/hot
public/storage
resources/scripts/wayfinder
resources/scripts/routeTree.gen.ts
resources/scripts/types/generated.d.ts
resources/scripts/types/typescript-transformer-manifest.json

# Local state that must not leak into a distributed image.
.env
.env.backup
.env.ci
storage/logs/*
storage/framework/cache/data/*
storage/framework/sessions/*
storage/framework/views/*
storage/*.key

# Development-only tooling and docs.
tests
docs
phpunit.xml
phpstan.neon
pint.json
.phpunit.cache
.phpunit.result.cache
.styleci.yml
stats.html
CODE_OF_CONDUCT.md
CONTRIBUTOR_LICENSE_AGREEMENT
CHANGELOG.md
AGENTS.md
CLAUDE.md

# The deployment tooling itself is delivered next to the compose file on the
# host, not baked into the image -- except docker/entrypoint.d, copied explicitly.
docker/install.sh
docker/convoyctl

**/.DS_Store
**/._.DS_Store
*.tmp.mjs
*.tmp.php
Loading
Loading