Skip to main content

max / makenotwork

Audit Run 20 remediations and mnw-cli todo update - Bump yara-x 1.14→1.15, aws-sdk-s3 1.119→1.131 - Config.host_url String→Arc<str> (eliminates 30+ clones) - Add #[tracing::instrument] to all embed handlers and payments functions - Split checkout.rs: extract helpers to checkout_helpers.rs - Replace .unwrap() with .expect() in creator_tiers.rs - Update audit_review.md to Run 20 - Mark mnw-cli pre-beta items complete
Co-Authored-By
Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-05 20:52 UTC
Commit: ad832b895fa611edb61b22abecc5a7b8b26b6e79
Parent: b01eea8
20 files changed, +600 insertions, -530 deletions
M server/Cargo.lock +135 -92
@@ -25,7 +25,7 @@
25 25 dependencies = [
26 26 "cfg-if",
27 27 "cipher",
28 - "cpufeatures",
28 + "cpufeatures 0.2.17",
29 29 ]
30 30
31 31 [[package]]
@@ -80,9 +80,9 @@
80 80
81 81 [[package]]
82 82 name = "annotate-snippets"
83 - version = "0.12.13"
83 + version = "0.12.15"
84 84 source = "registry+https://github.com/rust-lang/crates.io-index"
85 - checksum = "74fc7650eedcb2fee505aad48491529e408f0e854c2d9f63eb86c1361b9b3f93"
85 + checksum = "92570a3f9c98e7e84df84b71d0965ac99b1871fcd75a3773a3bd1bad13f64cf7"
86 86 dependencies = [
87 87 "anstyle",
88 88 "memchr",
@@ -159,7 +159,7 @@
159 159 dependencies = [
160 160 "base64ct",
161 161 "blake2",
162 - "cpufeatures",
162 + "cpufeatures 0.2.17",
163 163 "password-hash",
164 164 ]
165 165
@@ -320,7 +320,7 @@
320 320 "chrono",
321 321 "futures-util",
322 322 "hex",
323 - "hmac",
323 + "hmac 0.12.1",
324 324 "http-types",
325 325 "hyper 0.14.32",
326 326 "hyper-tls 0.5.0",
@@ -328,7 +328,7 @@
328 328 "serde_json",
329 329 "serde_path_to_error",
330 330 "serde_qs 0.10.1",
331 - "sha2",
331 + "sha2 0.10.9",
332 332 "smart-default",
333 333 "smol_str",
334 334 "thiserror 1.0.69",
@@ -380,8 +380,8 @@
380 380 "aws-sdk-ssooidc",
381 381 "aws-sdk-sts",
382 382 "aws-smithy-async",
383 - "aws-smithy-http 0.63.6",
384 - "aws-smithy-json 0.62.5",
383 + "aws-smithy-http",
384 + "aws-smithy-json",
385 385 "aws-smithy-runtime",
386 386 "aws-smithy-runtime-api",
387 387 "aws-smithy-types",
@@ -390,7 +390,7 @@
390 390 "fastrand 2.3.0",
391 391 "hex",
392 392 "http 1.4.0",
393 - "sha1",
393 + "sha1 0.10.6",
394 394 "time",
395 395 "tokio",
396 396 "tracing",
@@ -434,15 +434,15 @@
434 434
435 435 [[package]]
436 436 name = "aws-runtime"
437 - version = "1.7.2"
437 + version = "1.7.3"
438 438 source = "registry+https://github.com/rust-lang/crates.io-index"
439 - checksum = "5fc0651c57e384202e47153c1260b84a9936e19803d747615edf199dc3b98d17"
439 + checksum = "5dcd93c82209ac7413532388067dce79be5a8780c1786e5fae3df22e4dee2864"
440 440 dependencies = [
441 441 "aws-credential-types",
442 442 "aws-sigv4",
443 443 "aws-smithy-async",
444 444 "aws-smithy-eventstream",
445 - "aws-smithy-http 0.63.6",
445 + "aws-smithy-http",
446 446 "aws-smithy-runtime",
447 447 "aws-smithy-runtime-api",
448 448 "aws-smithy-types",
@@ -462,9 +462,9 @@
462 462
463 463 [[package]]
464 464 name = "aws-sdk-s3"
465 - version = "1.119.0"
465 + version = "1.131.0"
466 466 source = "registry+https://github.com/rust-lang/crates.io-index"
467 - checksum = "1d65fddc3844f902dfe1864acb8494db5f9342015ee3ab7890270d36fbd2e01c"
467 + checksum = "fe1b8c5282bf859170836045296b3cd710b7573aceb909498366bb508a41058e"
468 468 dependencies = [
469 469 "aws-credential-types",
470 470 "aws-runtime",
@@ -472,8 +472,9 @@
472 472 "aws-smithy-async",
473 473 "aws-smithy-checksums",
474 474 "aws-smithy-eventstream",
475 - "aws-smithy-http 0.62.6",
476 - "aws-smithy-json 0.61.9",
475 + "aws-smithy-http",
476 + "aws-smithy-json",
477 + "aws-smithy-observability",
477 478 "aws-smithy-runtime",
478 479 "aws-smithy-runtime-api",
479 480 "aws-smithy-types",
@@ -482,14 +483,14 @@
482 483 "bytes",
483 484 "fastrand 2.3.0",
484 485 "hex",
485 - "hmac",
486 + "hmac 0.13.0",
486 487 "http 0.2.12",
487 488 "http 1.4.0",
488 - "http-body 0.4.6",
489 + "http-body 1.0.1",
489 490 "lru",
490 491 "percent-encoding",
491 492 "regex-lite",
492 - "sha2",
493 + "sha2 0.11.0",
493 494 "tracing",
494 495 "url",
495 496 ]
@@ -503,8 +504,8 @@
503 504 "aws-credential-types",
504 505 "aws-runtime",
505 506 "aws-smithy-async",
506 - "aws-smithy-http 0.63.6",
507 - "aws-smithy-json 0.62.5",
507 + "aws-smithy-http",
508 + "aws-smithy-json",
508 509 "aws-smithy-observability",
509 510 "aws-smithy-runtime",
510 511 "aws-smithy-runtime-api",
@@ -527,8 +528,8 @@
527 528 "aws-credential-types",
528 529 "aws-runtime",
529 530 "aws-smithy-async",
530 - "aws-smithy-http 0.63.6",
531 - "aws-smithy-json 0.62.5",
531 + "aws-smithy-http",
532 + "aws-smithy-json",
532 533 "aws-smithy-observability",
533 534 "aws-smithy-runtime",
534 535 "aws-smithy-runtime-api",
@@ -551,8 +552,8 @@
551 552 "aws-credential-types",
552 553 "aws-runtime",
553 554 "aws-smithy-async",
554 - "aws-smithy-http 0.63.6",
555 - "aws-smithy-json 0.62.5",
555 + "aws-smithy-http",
556 + "aws-smithy-json",
556 557 "aws-smithy-observability",
557 558 "aws-smithy-query",
558 559 "aws-smithy-runtime",
@@ -569,26 +570,26 @@
569 570
570 571 [[package]]
571 572 name = "aws-sigv4"
572 - version = "1.4.2"
573 + version = "1.4.3"
573 574 source = "registry+https://github.com/rust-lang/crates.io-index"
574 - checksum = "b0b660013a6683ab23797778e21f1f854744fdf05f68204b4cca4c8c04b5d1f4"
575 + checksum = "68dc0b907359b120170613b5c09ccc61304eac3998ff6274b97d93ee6490115a"
575 576 dependencies = [
576 577 "aws-credential-types",
577 578 "aws-smithy-eventstream",
578 - "aws-smithy-http 0.63.6",
579 + "aws-smithy-http",
579 580 "aws-smithy-runtime-api",
580 581 "aws-smithy-types",
581 582 "bytes",
582 583 "crypto-bigint 0.5.5",
583 584 "form_urlencoded",
584 585 "hex",
585 - "hmac",
586 + "hmac 0.13.0",
586 587 "http 0.2.12",
587 588 "http 1.4.0",
588 589 "p256 0.11.1",
589 590 "percent-encoding",
590 591 "ring",
591 - "sha2",
592 + "sha2 0.11.0",
592 593 "subtle",
593 594 "time",
594 595 "tracing",
@@ -608,21 +609,22 @@
608 609
609 610 [[package]]
610 611 name = "aws-smithy-checksums"
611 - version = "0.63.12"
612 + version = "0.64.7"
612 613 source = "registry+https://github.com/rust-lang/crates.io-index"
613 - checksum = "87294a084b43d649d967efe58aa1f9e0adc260e13a6938eb904c0ae9b45824ae"
614 + checksum = "10efbbcec1e044b81600e2fc562a391951d291152d95b482d5b7e7132299d762"
614 615 dependencies = [
615 - "aws-smithy-http 0.62.6",
616 + "aws-smithy-http",
616 617 "aws-smithy-types",
617 618 "bytes",
618 619 "crc-fast",
619 620 "hex",
620 - "http 0.2.12",
621 - "http-body 0.4.6",
622 - "md-5",
621 + "http 1.4.0",
622 + "http-body 1.0.1",
623 + "http-body-util",
624 + "md-5 0.11.0",
623 625 "pin-project-lite",
624 - "sha1",
625 - "sha2",
626 + "sha1 0.11.0",
627 + "sha2 0.11.0",
626 628 "tracing",
627 629 ]
628 630
@@ -637,34 +639,13 @@
637 639 "crc32fast",
638 640 ]
639 641
640 - [[package]]
641 - name = "aws-smithy-http"
642 - version = "0.62.6"
643 - source = "registry+https://github.com/rust-lang/crates.io-index"
644 - checksum = "826141069295752372f8203c17f28e30c464d22899a43a0c9fd9c458d469c88b"
645 - dependencies = [
646 - "aws-smithy-eventstream",
647 - "aws-smithy-runtime-api",
648 - "aws-smithy-types",
649 - "bytes",
650 - "bytes-utils",
651 - "futures-core",
652 - "futures-util",
653 - "http 0.2.12",
654 - "http 1.4.0",
655 - "http-body 0.4.6",
656 - "percent-encoding",
657 - "pin-project-lite",
658 - "pin-utils",
659 - "tracing",
660 - ]
661 -
662 642 [[package]]
663 643 name = "aws-smithy-http"
664 644 version = "0.63.6"
665 645 source = "registry+https://github.com/rust-lang/crates.io-index"
666 646 checksum = "ba1ab2dc1c2c3749ead27180d333c42f11be8b0e934058fb4b2258ee8dbe5231"
667 647 dependencies = [
648 + "aws-smithy-eventstream",
668 649 "aws-smithy-runtime-api",
669 650 "aws-smithy-types",
670 651 "bytes",
@@ -710,15 +691,6 @@
710 691 "tracing",
711 692 ]
712 693
713 - [[package]]
714 - name = "aws-smithy-json"
715 - version = "0.61.9"
716 - source = "registry+https://github.com/rust-lang/crates.io-index"
717 - checksum = "49fa1213db31ac95288d981476f78d05d9cbb0353d22cdf3472cc05bb02f6551"
718 - dependencies = [
719 - "aws-smithy-types",
720 - ]
721 -
722 694 [[package]]
723 695 name = "aws-smithy-json"
724 696 version = "0.62.5"
@@ -749,12 +721,12 @@
749 721
750 722 [[package]]
751 723 name = "aws-smithy-runtime"
752 - version = "1.10.3"
724 + version = "1.11.1"
753 725 source = "registry+https://github.com/rust-lang/crates.io-index"
754 - checksum = "028999056d2d2fd58a697232f9eec4a643cf73a71cf327690a7edad1d2af2110"
726 + checksum = "0504b1ab12debb5959e5165ee5fe97dd387e7aa7ea6a477bfd7635dfe769a4f5"
755 727 dependencies = [
756 728 "aws-smithy-async",
757 - "aws-smithy-http 0.63.6",
729 + "aws-smithy-http",
758 730 "aws-smithy-http-client",
759 731 "aws-smithy-observability",
760 732 "aws-smithy-runtime-api",
@@ -774,11 +746,12 @@
774 746
775 747 [[package]]
776 748 name = "aws-smithy-runtime-api"
777 - version = "1.11.6"
749 + version = "1.12.0"
778 750 source = "registry+https://github.com/rust-lang/crates.io-index"
779 - checksum = "876ab3c9c29791ba4ba02b780a3049e21ec63dabda09268b175272c3733a79e6"
751 + checksum = "b71a13df6ada0aafbf21a73bdfcdf9324cfa9df77d96b8446045be3cde61b42e"
780 752 dependencies = [
781 753 "aws-smithy-async",
754 + "aws-smithy-runtime-api-macros",
782 755 "aws-smithy-types",
783 756 "bytes",
784 757 "http 0.2.12",
@@ -789,6 +762,17 @@
789 762 "zeroize",
790 763 ]
791 764
765 + [[package]]
766 + name = "aws-smithy-runtime-api-macros"
767 + version = "1.0.0"
768 + source = "registry+https://github.com/rust-lang/crates.io-index"
769 + checksum = "8d7396fd9500589e62e460e987ecb671bad374934e55ec3b5f498cc7a8a8a7b7"
770 + dependencies = [
771 + "proc-macro2",
772 + "quote",
773 + "syn 2.0.117",
774 + ]
775 +
792 776 [[package]]
793 777 name = "aws-smithy-types"
794 778 version = "1.4.7"
@@ -826,9 +810,9 @@
826 810
827 811 [[package]]
828 812 name = "aws-types"
829 - version = "1.3.14"
813 + version = "1.3.15"
830 814 source = "registry+https://github.com/rust-lang/crates.io-index"
831 - checksum = "47c8323699dd9b3c8d5b3c13051ae9cdef58fd179957c882f8374dd8725962d9"
815 + checksum = "2f4bbcaa9304ea40902d3d5f42a0428d1bd895a2b0f6999436fb279ffddc58ac"
832 816 dependencies = [
833 817 "aws-credential-types",
834 818 "aws-smithy-async",
@@ -1084,7 +1068,7 @@
1084 1068 source = "registry+https://github.com/rust-lang/crates.io-index"
1085 1069 checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
1086 1070 dependencies = [
1087 - "digest",
1071 + "digest 0.10.7",
1088 1072 ]
1089 1073
1090 1074 [[package]]
@@ -1096,6 +1080,15 @@
1096 1080 "generic-array",
1097 1081 ]
1098 1082
1083 + [[package]]
1084 + name = "block-buffer"
1085 + version = "0.12.0"
1086 + source = "registry+https://github.com/rust-lang/crates.io-index"
1087 + checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be"
1088 + dependencies = [
1089 + "hybrid-array",
1090 + ]
1091 +
1099 1092 [[package]]
1100 1093 name = "bstr"
1101 1094 version = "1.12.1"
@@ -1208,7 +1201,7 @@
1208 1201 source = "registry+https://github.com/rust-lang/crates.io-index"
1209 1202 checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
1210 1203 dependencies = [
1211 - "crypto-common",
1204 + "crypto-common 0.1.6",
1212 1205 "inout",
1213 1206 ]
1214 1207
@@ -1261,6 +1254,12 @@
1261 1254 "cc",
1262 1255 ]
1263 1256
1257 + [[package]]
1258 + name = "cmov"
1259 + version = "0.5.3"
1260 + source = "registry+https://github.com/rust-lang/crates.io-index"
1261 + checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746"
1262 +
1264 1263 [[package]]
1265 1264 name = "cobs"
1266 1265 version = "0.3.0"
@@ -1291,6 +1290,12 @@
1291 1290 source = "registry+https://github.com/rust-lang/crates.io-index"
1292 1291 checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
1293 1292
1293 + [[package]]
1294 + name = "const-oid"
1295 + version = "0.10.2"
1296 + source = "registry+https://github.com/rust-lang/crates.io-index"
1297 + checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
1298 +
1294 1299 [[package]]
1295 1300 name = "constant_time_eq"
1296 1301 version = "0.3.1"
@@ -1373,6 +1378,15 @@
1373 1378 "libc",
1374 1379 ]
1375 1380
1381 + [[package]]
1382 + name = "cpufeatures"
1383 + version = "0.3.0"
1384 + source = "registry+https://github.com/rust-lang/crates.io-index"
1385 + checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
1386 + dependencies = [
1387 + "libc",
1388 + ]
1389 +
1376 1390 [[package]]
1377 1391 name = "cranelift-assembler-x64"
1378 1392 version = "0.127.4"
@@ -1513,9 +1527,9 @@
1513 1527
1514 1528 [[package]]
1515 1529 name = "crc"
1516 - version = "3.4.0"
1530 + version = "3.3.0"
1517 1531 source = "registry+https://github.com/rust-lang/crates.io-index"
1518 - checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d"
1532 + checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
1519 1533 dependencies = [
1520 1534 "crc-catalog",
1521 1535 ]
@@ -1528,15 +1542,14 @@
1528 1542
1529 1543 [[package]]
1530 1544 name = "crc-fast"
1531 - version = "1.6.0"
1545 + version = "1.9.0"
1532 1546 source = "registry+https://github.com/rust-lang/crates.io-index"
1533 - checksum = "6ddc2d09feefeee8bd78101665bd8645637828fa9317f9f292496dbbd8c65ff3"
1547 + checksum = "2fd92aca2c6001b1bf5ba0ff84ee74ec8501b52bbef0cac80bf25a6c1d87a83d"
1534 1548 dependencies = [
1535 1549 "crc",
1536 - "digest",
1537 - "rand 0.9.2",
1538 - "regex",
1550 + "digest 0.10.7",
1539 1551 "rustversion",
1552 + "spin 0.10.0",
1540 1553 ]
1541 1554
1542 1555 [[package]]
@@ -1622,6 +1635,15 @@
1622 1635 "typenum",
1623 1636 ]
1624 1637
1638 + [[package]]
1639 + name = "crypto-common"
1640 + version = "0.2.1"
1641 + source = "registry+https://github.com/rust-lang/crates.io-index"
1642 + checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710"
1643 + dependencies = [
1644 + "hybrid-array",
1645 + ]
1646 +
1625 1647 [[package]]
1626 1648 name = "cssparser"
1627 1649 version = "0.35.0"
@@ -1666,6 +1688,15 @@
1666 1688 "memchr",
1667 1689 ]
1668 1690
1691 + [[package]]
1692 + name = "ctutils"
1693 + version = "0.4.2"
1694 + source = "registry+https://github.com/rust-lang/crates.io-index"
1695 + checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
1696 + dependencies = [
1697 + "cmov",
1698 + ]
1699 +
1669 1700 [[package]]
1670 1701 name = "darling"
1671 1702 version = "0.20.11"
@@ -1733,7 +1764,7 @@
1733 1764 source = "registry+https://github.com/rust-lang/crates.io-index"
1734 1765 checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
1735 1766 dependencies = [
1736 - "const-oid",
1767 + "const-oid 0.9.6",
1737 1768 "zeroize",
1738 1769 ]
1739 1770
@@ -1743,7 +1774,7 @@
1743 1774 source = "registry+https://github.com/rust-lang/crates.io-index"
1744 1775 checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
1745 1776 dependencies = [
1746 - "const-oid",
1777 + "const-oid 0.9.6",
1747 1778 "pem-rfc7468",
1748 1779 "zeroize",
1749 1780 ]
@@ -1792,12 +1823,24 @@
1792 1823 source = "registry+https://github.com/rust-lang/crates.io-index"
1793 1824 checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
1794 1825 dependencies = [
1795 - "block-buffer",
1796 - "const-oid",
1797 - "crypto-common",
1826 + "block-buffer 0.10.4",
1827 + "const-oid 0.9.6",
1828 + "crypto-common 0.1.6",
1798 1829 "subtle",
1799 1830 ]
1800 1831
1832 + [[package]]
1833 + name = "digest"
1834 + version = "0.11.3"
1835 + source = "registry+https://github.com/rust-lang/crates.io-index"
1836 + checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
1837 + dependencies = [
1838 + "block-buffer 0.12.0",
1839 + "const-oid 0.10.2",
1840 + "crypto-common 0.2.1",
1841 + "ctutils",
1842 + ]
1843 +
1801 1844 [[package]]
1802 1845 name = "displaydoc"
1803 1846 version = "0.2.5"
@@ -1843,12 +1886,12 @@
1843 1886 source = "registry+https://github.com/rust-lang/crates.io-index"
1844 1887 checksum = "48bc224a9084ad760195584ce5abb3c2c34a225fa312a128ad245a6b412b7689"
1845 1888 dependencies = [
1846 - "digest",
1889 + "digest 0.10.7",
1847 1890 "num-bigint-dig",
1848 1891 "num-traits",
1849 1892 "pkcs8 0.10.2",
1850 1893 "rfc6979 0.4.0",
1851 - "sha2",
1894 + "sha2 0.10.9",
Lines truncated
@@ -75,7 +75,7 @@
75 75 infer = "0.19"
76 76 goblin = "0.10"
77 77 zip = "8.2"
78 - yara-x = "1.14"
78 + yara-x = "1.15"
79 79
80 80 # CSV parsing (import system)
81 81 csv = "1.3"
@@ -1,7 +1,7 @@
1 1 # mnw-cli TODO
2 2
3 3 ## Status
4 - Done: Phases 1-8, Git proxy A-D (incl D5 DNS), UX audit fixes (8/8). Deployed 2026-05-03. Active: None. Next: PoM health check, astra test.
4 + Done: Phases 1-8, Git proxy A-D (incl D5 DNS), UX audit fixes (8/8), PoM health check, astra test. Deployed 2026-05-05. Active: None. Next: Post-beta features.
5 5
6 6 ---
7 7
@@ -30,7 +30,7 @@
30 30 - [x] D6: Restart sequence verified — admin SSH on 2200, mnw-cli on 22, both running — done 2026-04-22
31 31
32 32 ## Deploy
33 - - [ ] Test on astra (full TUI + SFTP + git push/pull)
33 + - [x] Test on astra (full TUI + SFTP + git push/pull) — tested from both macbook and astra; registered astra SSH key; fixed bare repo HEAD refs
34 34 - [x] Deploy to hetzner (cross-compile via deploy.sh) — done 2026-04-22
35 35 - [x] Verified: SSH auth, TUI launch, git ls-remote, git clone all working — 2026-04-22
36 36 - [x] Fixed: NoNewPrivileges blocking sudo for git ops — 2026-04-22
@@ -1,187 +1,164 @@
1 1 # MakeNotWork -- Audit Review
2 2
3 - **Last audited:** 2026-05-02 (Run 19, MNW server + doc fuzz)
4 - **Previous audit:** 2026-05-01 (Run 18, MNW server only)
3 + **Last audited:** 2026-05-04 (Run 20, MNW server full audit)
4 + **Previous audit:** 2026-05-02 (Run 19, MNW server + doc fuzz)
5 5
6 6 ## Overall Grade: A
7 7
8 - Run 19: 1,930 tests passing (1,220 unit + 679 integration + 28 doc + 3 load; 10 ignored), 0 failed. 0 cargo warnings. v0.4.8. ~81,384 LOC. 2 cold spots (0 bugs, 2 minor). Combined with doc fuzz for creator email readiness assessment. 10 test failures from Run 19 resolved 2026-05-04 (CSRF double-slash, SyncKit rate limiter key extraction, guest-free checkout CSRF exemption).
8 + Run 20: 678 integration tests passing (2 timing-sensitive sandbox rate-limit tests failing, non-critical), 0 cargo warnings. v0.4.10. ~83,232 LOC. 2 cold spots (0 bugs, 2 minor). Clean git status. `cargo check` passes cleanly.
9 9
10 10 ## Scorecard
11 11
12 12 | Dimension | Grade | Notes |
13 13 |-----------|:-----:|-------|
14 - | Code Quality | A | unwrap() in git/raw.rs fixed. helpers.rs split into formatting/crypto/rate_limit (395 lines from 1,268) |
15 - | Architecture | A | Inline SQL in route handlers still present (4 locations) but minor |
16 - | Testing | A | 1,930 tests, 0 failures. proptest active. 10 test failures fixed 2026-05-04 (CSRF, SyncKit rate limiter, guest-free exempt) |
17 - | Security | A+ | Zero SQL injection vectors, constant-time compare everywhere, fail-closed scanning, CSRF on all forms |
18 - | Performance | A | analytics.rs deduplicated (623->468 LOC). hash_lookup uses static reqwest::Client |
19 - | Documentation | A- | Module-level //! on every file. No README.md (CONTRIBUTING.md partially fills role) |
20 - | Dependencies | A- | Most deps current. tokio (1.49->1.50), uuid (1.20->1.22), chrono (0.4.43->0.4.44) pins stale |
21 - | Frontend | A | Askama auto-escape, all `\|safe` uses verified safe, no raw innerHTML. No CSP header (inline onclick pattern) |
22 - | Type Safety | A | 50+ UUID newtypes, validated string types, Cents monetary newtype. moderation.rs still uses raw Uuid |
23 - | Observability | A | Comprehensive #[instrument] coverage. Structured logging throughout |
24 - | Concurrency | A | ON CONFLICT, FOR UPDATE, atomic WHERE guards, advisory locks, optimistic versioning |
25 - | Resilience | A | Graceful shutdown with hard deadline. One missing timeout: payments/connect.rs:198 raw reqwest call |
26 - | API Consistency | A | Documented response conventions, json_error_layer, versioned SyncKit routes |
27 - | Migration Safety | A | 87 additive migrations, IF EXISTS on drops, CHECK constraints |
28 - | Codebase Size | A | 81K LOC well-organized. helpers.rs split complete. analytics.rs deduplicated |
14 + | Code Quality | A | Zero .unwrap() in production paths (3 LazyLock regex are acceptable) |
15 + | Architecture | A | Clean layer separation. Inline SQL only in health.rs (stats + probe, acceptable) |
16 + | Testing | A | ~1,214 test annotations, 94 integration test files, proptest active, comprehensive harness |
17 + | Security | A+ | Constant-time compare, fail-closed scanning, CSRF everywhere, Argon2id, HMAC webhooks, path traversal prevention |
18 + | Performance | A | Batch queries, pagination, CDN fallback, session touch cache, presigned uploads |
19 + | Documentation | A- | Module-level //! on all major files. No README.md (CONTRIBUTING.md fills role) |
20 + | Dependencies | A- | 3 transitive advisories (none exploitable). All security-sensitive deps on latest stable |
21 + | Frontend | A | Askama auto-escape, HTMX patterns consistent, CSP headers |
22 + | Type Safety | A+ | 36 UUID newtypes, 25+ domain enums, validated string types, Cents/PriceCents monetary newtypes |
23 + | Observability | A- | Comprehensive #[instrument] on routes + DB layer. Gaps: embed/ handlers (0 instruments), payments/ module (0 instruments) |
24 + | Concurrency | A | ON CONFLICT, FOR UPDATE, advisory locks, DashMap caches, atomic state changes |
25 + | Resilience | A | Graceful shutdown with 10s deadline, timeouts on all outbound calls, fail-closed scanning |
26 + | API Consistency | A | ListResponse wrapper, json_error_layer, versioned SyncKit routes, documented conventions |
27 + | Migration Safety | A | 93 additive migrations, IF NOT EXISTS guards, TIMESTAMPTZ throughout, defaults on all NOT NULL |
28 + | Codebase Size | A- | 83K LOC well-organized. 5 files over 500-line guideline (max 844). No egregious violations |
29 29
30 30 ## Module Heatmap
31 31
32 - | Module | Code | Arch | Test | Security | Perf | Docs | TypeSafe | Observ |
33 - |--------|:----:|:----:|:----:|:--------:|:----:|:----:|:--------:|:------:|
34 - | main.rs | A | A | n/a | A | n/a | A | n/a | A |
35 - | lib.rs | A | A | n/a | A | A- | A | A | n/a |
36 - | config.rs | A | A | A | A+ | n/a | A | n/a | n/a |
37 - | error.rs | A+ | A | A+ | A+ | n/a | A | A | A |
38 - | auth.rs | A | A | A- | A+ | n/a | A | A | A |
39 - | csrf.rs | A | A- | A | A | n/a | A | n/a | n/a |
40 - | helpers.rs | A- | n/a | A+ | A | n/a | A | A | n/a |
41 - | constants.rs | A | n/a | A | n/a | n/a | A | n/a | n/a |
42 - | storage.rs | A | A | A | A | n/a | A | A | n/a |
43 - | monitor.rs | A- | A | A | n/a | n/a | A | n/a | A |
44 - | wam_client.rs | A | n/a | **B** | n/a | n/a | A | n/a | n/a |
45 - | synckit_auth.rs | A | n/a | A+ | A+ | n/a | A | A | n/a |
46 - | pricing.rs | A | A+ | A+ | n/a | n/a | A | A | n/a |
47 - | wordlist.rs | A | n/a | n/a | n/a | n/a | A | n/a | n/a |
48 - | license_templates.rs | A | n/a | A | A- | n/a | A | A | n/a |
49 - | build_runner.rs | A | n/a | A- | A | n/a | A | n/a | A |
50 - | git_ssh.rs | A | A | A- | A | n/a | A | n/a | n/a |
51 - | rss.rs | A | n/a | A | A | A | A | n/a | n/a |
52 - | db/mod.rs | A | A | n/a | A | n/a | A | n/a | n/a |
53 - | db/id_types.rs | A | n/a | A | n/a | n/a | A | A+ | n/a |
54 - | db/enums.rs | A | n/a | A+ | n/a | n/a | A | A | n/a |
55 - | db/validated_types.rs | A | n/a | A+ | n/a | A | A | A | n/a |
56 - | db/users.rs | A | A | C | A | A | A | A- | n/a |
57 - | db/items.rs | A | A | C | A | A | A | **B+** | n/a |
58 - | db/synckit.rs | A | A | C | A | A- | A | A- | n/a |
59 - | db/creator_tiers.rs | A | A | A | A | A | A | A | n/a |
60 - | db/transactions.rs | A | A | C | A | A | A | A- | n/a |
61 - | db/analytics.rs | **B+** | **B+** | A | A | A | A | A- | n/a |
62 - | db/discover.rs | A- | **B+** | C | A | A | A | A | n/a |
63 - | db/subscriptions.rs | A | A | C | A | A | A | A | n/a |
64 - | db/promo_codes.rs | A | A | A+ | A | A | A | A | n/a |
65 - | db/models/* | A | A | A- | n/a | n/a | A | A | n/a |
66 - | db/moderation.rs | A | A | C | A | n/a | A- | **B** | n/a |
67 - | scanning/ | A | A | A+ | A+ | A | A | A | n/a |
68 - | payments/checkout.rs | A- | A | A | A | A- | A | A | n/a |
69 - | payments/webhooks.rs | A | A | A+ | A+ | n/a | A | n/a | n/a |
70 - | payments/connect.rs | A- | A | C | A | n/a | A | n/a | n/a |
71 - | email/tokens.rs | A | A | A+ | A+ | n/a | A | n/a | n/a |
72 - | email/notifications.rs | A | A | C | n/a | n/a | A | n/a | n/a |
73 - | validation/ | A | A | A+ | A+ | n/a | A | A | n/a |
74 - | types/mod.rs | A | A | A+ | A+ | n/a | A | A- | n/a |
75 - | types/conversions.rs | A | A | A | n/a | n/a | A | A- | n/a |
76 - | templates/ | A | A | n/a | A | n/a | A | n/a | n/a |
77 - | scheduler/mod.rs | A | A | A+ | n/a | n/a | A | n/a | n/a |
78 - | scheduler/other | A | A | C | n/a | n/a | A | n/a | A |
79 - | import/csv_converter.rs | A | A | A+ | A | A- | A | n/a | n/a |
80 - | git/mod.rs | A | A | A | A | A | A | A | n/a |
81 - | routes/auth.rs | A | A | C | A+ | A | A | A | A |
82 - | routes/admin/ | A | A | C | A | **B** | A | A | A |
83 - | routes/storage/ | A | A | C | A | A | A | A | A |
84 - | routes/stripe/ | A | **B** | C | A | A | A | A | A |
85 - | routes/synckit/ | A | A | C | A | A | A | A | A |
86 - | routes/postmark/ | A | A | A | A | A | A | n/a | A |
87 - | routes/git/ | **B** | A | C | A | **B** | A | A | A |
88 - | routes/pages/ | A | **B** | C | A | A | A | A | A |
89 - | routes/api/ | A | A | C | A | A | A | A | **B** |
90 - | routes/builds.rs | A | A | C | A | A | A | A | A |
91 - | routes/ota.rs | A | A | C | A | **B** | A | A | A |
92 - | tests/ | A | A | n/a | A | n/a | A | n/a | n/a |
32 + | Module | Code | Arch | Test | Security | Perf | Docs | TypeSafe | Observ | Size |
33 + |--------|:----:|:----:|:----:|:--------:|:----:|:----:|:--------:|:------:|:----:|
34 + | lib.rs + main.rs | A | A | B+ | A | A | A | A | A | A |
35 + | config.rs | A | A | A | A | n/a | A | A | B+ | A |
36 + | error.rs | A | A | A | A | n/a | A | A | A | A |
37 + | auth.rs | A | A | A- | A+ | A | A | A | A | A |
38 + | csrf.rs | A | A | A | A | A- | A | A | A- | A |
39 + | helpers.rs | A | A | A | A | A | A | A- | B+ | A |
40 + | constants.rs | A | n/a | A | A | n/a | A- | A | n/a | A |
41 + | rate_limit.rs | A | A | A | A | A | A | A | B+ | A |
42 + | storage.rs | A | A | A | A | A | A | A | B+ | A |
43 + | pricing.rs | A | A+ | A+ | A | A | A | A | n/a | A |
44 + | crypto.rs | A | A | A | A | A | A | A | n/a | A |
45 + | formatting.rs | A | A | A+ | A | A | A | A | n/a | A |
46 + | rss.rs | A | A | A | A | A | A | A- | n/a | A |
47 + | synckit_auth.rs | A | A | A | A | A | A | A | B+ | A |
48 + | db/enums.rs | A | A | A | A | n/a | A | A+ | n/a | A |
49 + | db/id_types.rs | A | A | A | n/a | n/a | A | A+ | n/a | A |
50 + | db/validated_types.rs | A | A | A+ | A | A | A | A+ | n/a | A |
51 + | db/users.rs | A | A | B | A | A- | A | A | A | A |
52 + | db/items.rs | A | A | B | A | A- | A | A | A | A |
53 + | db/synckit.rs | A | A | B | A | A | A | A | A | A |
54 + | db/transactions.rs | A | A | B | A | A | A | A | A | A |
55 + | db/discover.rs | A | A | B | A | A | A | A | n/a | A |
56 + | db/creator_tiers.rs | A | A | A | A | A | A | A | n/a | A |
57 + | db/models/* | A | A | B+ | A | n/a | A- | A | n/a | A |
58 + | types/ | A | A | B | A | n/a | A | A | n/a | A |
59 + | scanning/ | A | A+ | A+ | A+ | A- | A | A | B | A |
60 + | payments/ | A | A | A- | A | A- | A | A | **B+** | B+ |
61 + | email/ | A | A | A | A | A- | A | A | B+ | A- |
62 + | scheduler/ | A | A | B+ | A | A | A | A | A- | A |
63 + | validation/ | A | A | A+ | A+ | A | B+ | A | n/a | A |
64 + | import/ | A | A | A | A | B+ | A- | A | B+ | A |
65 + | git/ | A | A | A | A+ | B+ | A- | A | B | A |
66 + | git_ssh.rs | A | A | A | A | A | A- | A | B+ | A |
67 + | build_runner.rs | A | A- | B+ | A+ | A | A- | A | A | A |
68 + | monitor.rs | A | A | A- | A | A | A | A | A | A |
69 + | templates/ | A | A | n/a | A | A | A- | A | B | B+ |
70 + | routes/auth.rs | A | A | n/a | A+ | A | A | A | A | A |
71 + | routes/oauth.rs | A | A | n/a | A+ | A | A | A | A | A- |
72 + | routes/admin/ | A | A | n/a | A | A | A | A | A | A |
73 + | routes/api/ | A | A | n/a | A | A | A | A | A | **B+** |
74 + | routes/stripe/ | A | A | n/a | A | A | A | A | **B+** | **B+** |
75 + | routes/synckit/ | A | A | n/a | A | A | A | A | A | A |
76 + | routes/pages/ | A | A | n/a | A | A | A | A | A- | **B+** |
77 + | routes/embed/ | A | A | n/a | A | A | A- | A | **B** | A |
78 + | routes/git/ | A | A | n/a | A | A | A | A | A | A |
79 + | routes/storage/ | A | A | n/a | A | A | A | A | A | A |
80 + | routes/postmark/ | A | A | n/a | A | A | A | n/a | A- | B+ |
93 81
94 82 **Bold** = cold spot (B or below).
95 83
96 84 ### Cold Spots
97 85
98 - 1. **db/moderation.rs type safety (B):** Uses raw `Uuid` for action IDs and `String` for action_type instead of typed newtypes. Only file in db/ without typed IDs. (Carried from Run 18)
99 - 2. **payments/connect.rs resilience (B):** Missing timeout on raw reqwest call to Stripe resume-subscription API at line 198. Only unprotected outbound HTTP call in the codebase.
86 + 1. **routes/embed/ observability (B):** Zero `#[tracing::instrument]` on any embed handler (item.rs, project.rs, user.rs). Embeds serve third-party traffic — blind spot for latency monitoring.
87 + 2. **routes/stripe/webhook/checkout.rs size (B+) + observability (B+):** 792 LOC (above 500-line guideline), internal `handle_*` functions lack `#[instrument]`.
100 88
101 - ### Resolved Cold Spots (from Run 18)
102 - - ~~routes/git/raw.rs unwrap()~~ -- Fixed
103 - - ~~db/analytics.rs duplication~~ -- Fixed (Scope enum extraction)
104 - - ~~wam_client.rs testing~~ -- Fixed (5 tests added)
89 + ### Resolved Cold Spots (from Run 19)
90 +
91 + - ~~db/moderation.rs type safety (B)~~ -- Fixed (typed IDs added)
92 + - ~~payments/connect.rs resilience (B)~~ -- Fixed (raw reqwest call removed/restructured)
105 93
106 94 ## Mandatory Surprise
107 95
108 - **Hand-rolled Stripe v2 webhook signature verification.** `payments/webhooks.rs:184-228` implements v2 webhook signature verification from scratch because the `stripe` crate only supports v1. The implementation correctly parses `t=,v1=` headers, rejects timestamps >300s in either direction (replay + clock skew), and uses `hmac::Hmac::verify_slice()` which is constant-time via the `subtle` crate. Both past and future timestamp bounds are checked. Well-tested with 26 unit tests including edge cases (stale, future, wrong secret, within tolerance).
96 + **Unexpectedly good:** The `scanning` module (2,110 LOC) implements production-grade 6-layer anti-malware infrastructure. The archive layer doesn't trust ZIP central directory size claims -- it actually decompresses entries counting bytes with an abort threshold (archive.rs:83-107). The structural analysis layer detects VMProtect-packed and UPX-packed binaries by exact section name matching to avoid false positives. ZIP bomb detection uses both compression ratio AND actual decompression byte counting. This is far above what most content platforms implement and would be impressive in a dedicated security product.
109 97
110 98 ### Previous Surprises
111 99
100 + **Run 19:** Hand-rolled Stripe v2 webhook signature verification with replay protection.
101 +
112 102 **Run 18:** Sandbox tier mismatch bug (SmallFiles vs small_files). Fixed.
113 103
114 104 **Run 17:** TOCTOU-safe slug generation with retry loop + advisory lock pattern for sandbox IP cap.
115 105
116 - **Run 15:** Session touch cache — DashMap with 30s TTL avoids N+1 session queries.
117 -
118 - **Run 13:** Mailing list delivery migration has zero duplication with the follows-based delivery it replaces.
106 + **Run 15:** Session touch cache -- DashMap with 30s TTL avoids N+1 session queries.
119 107
120 108 ## Strengths
121 109
122 110 ### 1. Security-in-depth
123 - Zero SQL injection vectors across 200+ queries. Argon2id with explicit params, CSRF synchronizer tokens with constant-time comparison, session fixation prevention, account lockout, rate limiting, HMAC-signed URLs, 6-layer malware scanning pipeline with fail-closed design. JWT tokens validated against live DB state (not just expiry). Comprehensive CSP headers.
111 + Zero SQL injection vectors across 200+ queries. Argon2id with explicit params (46MiB/2 iterations), CSRF synchronizer tokens with constant-time comparison, session fixation prevention, account lockout, rate limiting, HMAC-signed URLs, 6-layer malware scanning pipeline with fail-closed design. ZIP bomb detection, path traversal prevention in archives, shell command validation in build runner.
124 112
125 - ### 2. Test quality and coverage
126 - 1,933 tests with per-test database isolation (CREATE DATABASE TEMPLATE clone). 53 adversarial exploit-attempt tests. Property-based testing with proptest. Behavior-focused integration tests via in-process tower::ServiceExt::oneshot. Zero TODO/FIXME/HACK in the codebase.
113 + ### 2. Type safety discipline
114 + 36 UUID newtypes via `define_pg_uuid_id!`, 25+ domain enums via `impl_str_enum!`, validated string types (Username, Slug, KeyCode), Cents/PriceCents monetary newtypes with proptest coverage. Compile-time template verification via Askama. Proof-carrying types: once constructed, guaranteed valid.
127 115
128 - ### 3. Type safety discipline
129 - 50+ UUID newtypes via `define_pg_uuid_id!` macro, 23 domain enums via `impl_str_enum!`, validated string types (Username, Slug, KeyCode), Cents monetary newtype with SUM(BIGINT)->NUMERIC decode handling. Compile-time template verification via Askama.
116 + ### 3. Test quality
117 + 1,214+ test annotations with per-test database isolation. Property-based testing with proptest (pricing, formatting, validated types). Adversarial tests cover SQL injection, XSS, path traversal, formula injection, ZIP bombs. Integration harness mocks all external dependencies (Stripe, S3, Postmark, ClamAV).
130 118
131 119 ## Weaknesses
132 120
133 - ### 1. Inline SQL in route handlers
134 - 4 locations where route handlers contain raw `sqlx::query` calls instead of delegating to `db/`:
135 - - `routes/stripe/checkout/project.rs:90` — INSERT for free project claim
136 - - `routes/pages/dashboard/forms.rs:58,71` — SUM queries for storage display
137 - - `routes/pages/public/landing.rs:46` — COUNT for landing page stats
121 + ### 1. Observability gaps in embed/ and payments/
122 + The embed module (serving third-party iframe traffic) and payments module (handling money) have zero `#[instrument]` annotations. These are high-value modules where tracing would provide the most benefit.
138 123
139 - ### 2. Sandbox tier bug (confirmed)
140 - `'SmallFiles'` vs `'small_files'` mismatch silently breaks sandbox user tier detection.
124 + ### 2. Five files above 500-line size guideline
125 + health.rs (844), webhook/checkout.rs (792), exports.rs (737), license_keys.rs (741), tabs/user.rs (707). None are egregious but represent opportunities for extraction.
141 126
142 - ### 3. CSV import amount heuristic
143 - `import/csv_converter.rs` `parse_amount_cents` uses a 10,000 threshold heuristic to guess whether amounts are in cents or dollars. Values in the 100-10,000 range (e.g., $99 as `9900` cents) are silently misinterpreted as dollar amounts ($9,900). No explicit cents/dollars column indicator.
127 + ### 3. async-trait still in use
128 + 3 trait definitions still use `async-trait` crate instead of Rust 2024 native async traits (StorageBackend, EmailTransport, PaymentProvider). Chronic -- carried from Run 18.
144 129
145 130 ## Action Items
146 131
147 - ### Run 19 (2026-05-02)
132 + ### Run 20 (2026-05-04)
148 133
149 - 51. **[MEDIUM]** Add timeout to `payments/connect.rs:198` raw reqwest call to Stripe resume-subscription API
150 - 52. **[MEDIUM]** Add `ModerationActionId` newtype and `ModerationActionType` enum to `db/moderation.rs` (carried from Run 18 #41)
151 - 53. **[LOW]** Add README.md to server/ with setup instructions and architecture overview link
152 - 54. **[LOW]** Bump dependency pins: tokio 1.49->1.50, uuid 1.20->1.22, chrono 0.4.43->0.4.44, yara-x 1.13->1.14, anyhow 1.0.101->1.0.102
153 - 55. **[DEFERRED]** Extract inline SQL from route handlers to db/ layer (4 locations, carried from Run 18 #40)
154 - 56. **[DEFERRED]** Remove `async-trait` in favor of Rust 2024 native async traits (carried from Run 18 #50)
155 - 57. **[DEFERRED]** Migrate inline `onclick` handlers to `addEventListener` to enable strict CSP
134 + 58. **[MEDIUM]** Add `#[tracing::instrument(skip_all)]` to all handlers in routes/embed/ (item.rs, project.rs, user.rs)
135 + 59. **[MEDIUM]** Add `#[tracing::instrument(skip_all)]` to functions in payments/ (checkout.rs, connect.rs, webhooks.rs)
136 + 60. **[LOW]** Split routes/stripe/webhook/checkout.rs (792 LOC) -- extract handle_* functions to submodule
137 + 61. **[LOW]** Bump transitive deps: yara-x (for intaglio fix), AWS SDK chain (for rustls-webpki fix)
138 + 62. **[DEFERRED]** Remove `async-trait` in favor of Rust 2024 native async traits (chronic, carried from Run 18 #56)
139 + 63. **[DEFERRED]** Add README.md to server/ (carried from Run 19 #53)
140 + 64. **[DEFERRED]** Split oversized route files: exports.rs, license_keys.rs, health.rs, tabs/user.rs
156 141
157 142 ### Open (blocked on upstream)
143 +
158 144 23. Monitor aws-sdk-s3 for lru fix (RUSTSEC-2026-0002)
159 145 24. Monitor async-stripe for instant fix (RUSTSEC-2024-0384)
160 146 25. Monitor aws-sdk-s3 for rustls-webpki 0.101.7 fix (RUSTSEC-2026-0049)
161 - 33. bincode unmaintained (RUSTSEC-2025-0141) — upstream via syntect/yara-x, warning only
147 + 33. bincode unmaintained (RUSTSEC-2025-0141) -- upstream via syntect/yara-x, warning only
162 148
163 - ### Previously resolved
164 - All items 1-22, 31-38, and most Run 18 items verified intact.
165 -
166 - ## Previous Action Item Verification (Run 18)
149 + ## Previous Action Item Verification (Run 19)
167 150
168 151 | # | Item | Status |
169 152 |---|------|--------|
170 - | 39 | Sandbox tier bug (`'SmallFiles'`->`'small_files'`) | Fixed |
171 - | 40 | Extract inline SQL from route handlers | Unfixed (carried as #55) |
172 - | 41 | Moderation typed IDs | Unfixed (carried as #52) |
173 - | 42 | `.unwrap()` in git/raw.rs | Fixed |
174 - | 43 | Missing `#[instrument]` on public_projects | Fixed |
175 - | 44 | `.unwrap()` in helpers.rs | Fixed (helpers.rs split) |
176 - | 45 | `.unwrap()` in monitor.rs | Fixed |
177 - | 46 | wam_client.rs unit tests | Fixed (5 tests added) |
178 - | 47 | CSV import cents/dollars format | Fixed (heuristic removed) |
179 - | 48 | Split helpers.rs | Fixed (1,268->395 lines: formatting.rs, crypto.rs, rate_limit.rs) |
180 - | 49 | Analytics.rs deduplication | Fixed (623->468 lines via Scope enum) |
181 - | 50 | Remove async-trait | Unfixed (carried as #56) |
182 - | 23-25, 33 | Upstream dep advisories | Unfixed (chronic, upstream-blocked) |
153 + | 51 | Add timeout to payments/connect.rs raw reqwest call | Fixed (call restructured) |
154 + | 52 | Add ModerationActionId newtype to db/moderation.rs | Fixed |
155 + | 53 | Add README.md to server/ | Unfixed (carried as #63) |
156 + | 54 | Bump dependency pins (tokio, uuid, chrono, yara-x, anyhow) | Fixed (all at latest) |
157 + | 55 | Extract inline SQL from route handlers (4 locations) | Fixed (only health.rs COUNT stats remain -- acceptable) |
158 + | 56 | Remove async-trait | Unfixed (chronic, carried as #62) |
159 + | 57 | Migrate onclick to addEventListener for strict CSP | Fixed (via dashboard usability rework) |
183 160
184 - 10 of 12 Run 18 items fixed. 2 carried forward. No regressions.
161 + 5 of 7 Run 19 items fixed. 2 carried forward (1 chronic). No regressions.
185 162
186 163 ## Metrics Over Time
187 164
@@ -205,6 +182,7 @@
205 182 | 2026-04-30 (Run 17) | ~79,334 | -- | 1,861 | ~15.0 | 0 | 0 | A |
206 183 | 2026-05-01 (Run 18) | ~80,470 | -- | 1,933 (34 int. fail) | ~15.1 | 0 | 5 | A |
207 184 | 2026-05-02 (Run 19) | ~81,384 | -- | 1,923 (0 fail) | ~23.6 | 0 | 2 | A |
185 + | 2026-05-04 (Run 20) | ~83,232 | 238 | 1,214+ annotations | ~14.6 | 0 | 2 | A |
208 186
209 187 ---
210 188
@@ -512,7 +512,7 @@
512 512 host: "127.0.0.1".parse().unwrap(),
513 513 port: 3000,
514 514 database_url: "postgres://test".to_string(),
515 - host_url: "http://localhost:3000".to_string(),
515 + host_url: std::sync::Arc::from("http://localhost:3000"),
516 516 signing_secret: "secret".to_string(),
517 517 storage: None,
518 518 synckit_storage: None,
@@ -575,7 +575,7 @@
575 575 host: "127.0.0.1".parse().unwrap(),
576 576 port: 3000,
577 577 database_url: "postgres://test".to_string(),
578 - host_url: "http://localhost:3000".to_string(),
578 + host_url: std::sync::Arc::from("http://localhost:3000"),
579 579 signing_secret: "secret".to_string(),
580 580 storage: None,
581 581 synckit_storage: None,
@@ -2,6 +2,7 @@
2 2
3 3 use std::collections::HashMap;
4 4 use std::net::{IpAddr, SocketAddr};
5 + use std::sync::Arc;
5 6
6 7 use crate::db::{CreatorTier, UserId};
7 8
@@ -14,8 +15,9 @@
14 15 pub port: u16,
15 16 /// Database connection URL
16 17 pub database_url: String,
17 - /// Public-facing host URL (e.g., "https://makenot.work" or "localhost:3000")
18 - pub host_url: String,
18 + /// Public-facing host URL (e.g., "https://makenot.work" or "localhost:3000").
19 + /// Stored as `Arc<str>` so cloning into spawned tasks / templates is cheap.
20 + pub host_url: Arc<str>,
19 21 /// Secret key for signing tokens (password reset, email verification, etc.)
20 22 pub signing_secret: String,
21 23 /// S3-compatible storage configuration (optional)
@@ -202,7 +204,7 @@
202 204 host,
203 205 port,
204 206 database_url,
205 - host_url,
207 + host_url: Arc::from(host_url),
206 208 signing_secret,
207 209 storage,
208 210 synckit_storage,
@@ -475,7 +477,7 @@
475 477 host: "127.0.0.1".parse().unwrap(),
476 478 port: 8080,
477 479 database_url: "postgres://test".to_string(),
478 - host_url: "http://localhost:8080".to_string(),
480 + host_url: Arc::from("http://localhost:8080"),
479 481 signing_secret: "secret".to_string(),
480 482 storage: None,
481 483 synckit_storage: None,
@@ -4,6 +4,6 @@
4 4 edition = "2024"
5 5
6 6 [dependencies]
7 - aws-sdk-s3 = "1.119"
7 + aws-sdk-s3 = "1.131"
8 8 aws-config = { version = "1.8", features = ["behavior-version-latest"] }
9 9 tracing = "0.1"