···11+{"id":"hcs-01nd","title":"MEDIUM: Validate Sec-WebSocket-Version header during handshake","status":"closed","priority":2,"issue_type":"bug","created_at":"2026-01-06T11:52:50.538107666+01:00","created_by":"gdiazlo","updated_at":"2026-01-06T12:09:43.205539723+01:00","closed_at":"2026-01-06T12:09:43.205539723+01:00","close_reason":"Added validate_websocket_version function to websocket.ml. Server now validates Sec-WebSocket-Version header per RFC 6455, responding with 426 Upgrade Required and supported version (13) if invalid."}
22+{"id":"hcs-02q7","title":"Add security-focused fuzz testing for HTTP parsing","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T11:52:51.912443162+01:00","created_by":"gdiazlo","updated_at":"2026-01-06T11:52:51.912443162+01:00"}
13{"id":"hcs-0bi","title":"docs: Create docs/ folder structure and README","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-03T00:44:13.323975386+01:00","updated_at":"2026-01-03T00:47:16.216273256+01:00","closed_at":"2026-01-03T00:47:16.216273256+01:00"}
24{"id":"hcs-0ro","title":"Implement WebSocket frame types and parsing","description":"Implement WebSocket wire format in hcs-core/ws_frame.ml:\n\n```ocaml\ntype frame =\n | Text of string\n | Binary of Cstruct.t\n | Ping of Cstruct.t\n | Pong of Cstruct.t\n | Close of int option * string option\n\ntype parse_result =\n | Complete of frame * int (* frame and bytes consumed *)\n | Incomplete of int (* need more bytes *)\n | Error of string\n\nval parse_frame : Cstruct.t -\u003e parse_result\nval serialize_frame : ?mask:bool -\u003e frame -\u003e Cstruct.t\n\n(* Handshake *)\nval make_handshake_request : Uri.t -\u003e ?protocols:string list -\u003e Headers.t -\u003e request\nval validate_handshake_response : response -\u003e (string option, string) result (* selected protocol *)\nval make_handshake_response : request -\u003e ?protocol:string -\u003e (response, string) result\n```\n\nPure parsing/serialization.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T14:34:32.864373772+01:00","updated_at":"2025-12-29T16:00:43.877842667+01:00","closed_at":"2025-12-29T16:00:43.877842667+01:00","dependencies":[{"issue_id":"hcs-0ro","depends_on_id":"hcs-lhr","type":"parent-child","created_at":"2025-12-29T14:34:52.111489961+01:00","created_by":"gdiazlo","metadata":"{}"}]}
35{"id":"hcs-0y4","title":"Implement compression middleware with gzip and zstd support","status":"closed","priority":1,"issue_type":"feature","created_at":"2026-01-01T18:44:00.161388436+01:00","updated_at":"2026-01-01T18:53:17.947904901+01:00","closed_at":"2026-01-01T18:53:17.947904901+01:00"}
···5153{"id":"hcs-8br","title":"Implement Cancel module","description":"Implement cooperative cancellation in hcs-core/cancel.ml:\n\n```ocaml\nmodule Cancel : sig\n type t\n \n val create : unit -\u003e t\n val cancel : t -\u003e unit\n val is_cancelled : t -\u003e bool\n val check : t -\u003e (unit, error) result (* Returns Error Cancelled if cancelled *)\n \n (* Combine multiple tokens - cancelled if any is cancelled *)\n val any : t list -\u003e t\nend\n```\n\nImplementation: Use an Atomic.t bool internally for thread-safety. The `any` combinator creates a new token that polls children.\n\nThis is the core, runtime-agnostic cancellation. Runtime-specific implementations (Eio.Cancel, Lwt.cancel) will wrap this or provide their own.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-29T14:29:20.005246967+01:00","updated_at":"2025-12-29T14:56:31.063102088+01:00","closed_at":"2025-12-29T14:56:31.063102088+01:00","labels":["core"],"dependencies":[{"issue_id":"hcs-8br","depends_on_id":"hcs-pnc","type":"parent-child","created_at":"2025-12-29T14:30:09.074639524+01:00","created_by":"gdiazlo","metadata":"{}"}]}
5254{"id":"hcs-8zr","title":"Implement HTTP/1.1 client parser/serializer","description":"Implement HTTP/1.1 wire format in hcs-core/h1.ml:\n\n```ocaml\n(* Request serialization *)\nval serialize_request : request -\u003e Cstruct.t\nval serialize_request_head : request -\u003e Cstruct.t (* without body *)\n\n(* Response parsing *)\ntype parse_result = \n | Complete of response * int (* response and bytes consumed *)\n | Incomplete of int (* need more bytes, minimum *)\n | Error of string\n\nval parse_response_head : Cstruct.t -\u003e parse_result\n\n(* Chunked transfer encoding *)\nval parse_chunk_header : Cstruct.t -\u003e (int * int, string) result (* size, header_len *)\nval serialize_chunk : Cstruct.t -\u003e Cstruct.t\nval serialize_last_chunk : Cstruct.t\n```\n\nPure parsing/serialization, no IO. Use zero-copy where possible with Cstruct views.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-29T14:31:17.431899471+01:00","updated_at":"2025-12-29T14:56:37.246977449+01:00","closed_at":"2025-12-29T14:56:37.246977449+01:00","dependencies":[{"issue_id":"hcs-8zr","depends_on_id":"hcs-qnb","type":"parent-child","created_at":"2025-12-29T14:31:46.61571522+01:00","created_by":"gdiazlo","metadata":"{}"}]}
5355{"id":"hcs-9076","title":"Update: Migrate las.ml to new architecture","description":"Rewrite bin/las/las.ml using new three-layer architecture:\n\n1. Endpoint with global plugs (logger, session, static)\n2. Router with pipelines (browser pipeline for web, api pipeline for JSON)\n3. Per-route plugs where needed (auth on protected routes)\n\nThis validates the new API design works in practice.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-03T21:12:08.460666471+01:00","created_by":"gdiazlo","updated_at":"2026-01-03T21:31:10.900440039+01:00","closed_at":"2026-01-03T21:31:10.900440039+01:00","close_reason":"Migrated las.ml","dependencies":[{"issue_id":"hcs-9076","depends_on_id":"hcs-1lvl","type":"parent-child","created_at":"2026-01-03T21:13:04.669576954+01:00","created_by":"gdiazlo"},{"issue_id":"hcs-9076","depends_on_id":"hcs-cf24","type":"blocks","created_at":"2026-01-03T21:14:00.272954069+01:00","created_by":"gdiazlo"},{"issue_id":"hcs-9076","depends_on_id":"hcs-z64a","type":"blocks","created_at":"2026-01-03T21:14:05.330540394+01:00","created_by":"gdiazlo"}]}
5656+{"id":"hcs-93bu","title":"HIGH: Use constant-time comparison in Basic Auth password validation","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-06T11:52:49.188137327+01:00","created_by":"gdiazlo","updated_at":"2026-01-06T12:08:19.344887122+01:00","closed_at":"2026-01-06T12:08:19.344887122+01:00","close_reason":"Added secure_compare function to basic_auth.ml. Updated create_static and create_with_map to use constant-time string comparison for password validation, preventing timing attacks."}
5457{"id":"hcs-9dz","title":"Clean up duplicate implementations: remove non-optimized functions and rename optimized ones","status":"closed","priority":1,"issue_type":"chore","created_at":"2025-12-30T21:00:09.361966265+01:00","updated_at":"2025-12-30T21:08:48.343581414+01:00","closed_at":"2025-12-30T21:08:48.343581414+01:00"}
5558{"id":"hcs-9gav","title":"docs: Plugs Reference (all built-in plugs)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-03T00:44:53.585873271+01:00","updated_at":"2026-01-03T01:03:38.273529229+01:00","closed_at":"2026-01-03T01:03:38.273529229+01:00"}
5659{"id":"hcs-9l7","title":"docs: Writing Custom Plugs guide","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-03T00:44:48.545112929+01:00","updated_at":"2026-01-03T01:20:01.380747222+01:00","closed_at":"2026-01-03T01:20:01.380747222+01:00"}
···107110{"id":"hcs-hkf","title":"Add benchmark runner script with standard scenarios","description":"Create a benchmark runner script (bench/run_benchmarks.sh) that runs standard benchmark scenarios:\n1. Minimal GET (/ping) - pure overhead measurement\n2. Small payload (1KB) - typical API response\n3. Medium payload (10KB) - larger JSON responses \n4. Large payload (100KB) - file downloads\n5. POST with body - request body handling\n6. Varying concurrency (1, 10, 50, 100, 200 connections)\n7. HTTP/1.1 vs HTTP/2 comparison\n\nOutput results to bench/results/ with timestamps for tracking over time.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-29T18:04:02.294539956+01:00","updated_at":"2025-12-29T18:17:10.742622288+01:00","closed_at":"2025-12-29T18:17:10.742622288+01:00","dependencies":[{"issue_id":"hcs-hkf","depends_on_id":"hcs-jtz","type":"parent-child","created_at":"2025-12-29T18:04:24.660841757+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-hkf","depends_on_id":"hcs-4w8","type":"blocks","created_at":"2025-12-29T18:04:36.967445707+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-hkf","depends_on_id":"hcs-320","type":"blocks","created_at":"2025-12-29T18:04:38.425355179+01:00","created_by":"gdiazlo","metadata":"{}"}]}
108111{"id":"hcs-i4f","title":"Setup bench/ directory structure with .gitignore","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-30T22:21:21.51511238+01:00","updated_at":"2025-12-30T22:23:03.029513364+01:00","closed_at":"2025-12-30T22:23:03.029513364+01:00"}
109112{"id":"hcs-i8j","title":"Implement OCaml/HCS benchmark server (plaintext + json, HTTP/1+2, CPU scaling)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-30T22:21:36.638072425+01:00","updated_at":"2025-12-30T22:28:28.339092129+01:00","closed_at":"2025-12-30T22:28:28.339092129+01:00"}
113113+{"id":"hcs-ibm9","title":"CRITICAL: Replace Random.int with cryptographic RNG in security-sensitive code","status":"closed","priority":0,"issue_type":"bug","created_at":"2026-01-06T11:52:43.595353531+01:00","created_by":"gdiazlo","updated_at":"2026-01-06T11:56:42.553380409+01:00","closed_at":"2026-01-06T11:56:42.553380409+01:00","close_reason":"Replaced Random.int with Mirage_crypto_rng in CSRF, session, token, and WebSocket modules"}
110114{"id":"hcs-j2z","title":"Implement unified Client module (Eio)","description":"Implement unified client API in hcs-eio/client.ml:\n\n```ocaml\ntype t\n\nval create :\n sw:Eio.Switch.t -\u003e\n net:Eio.Net.t -\u003e\n clock:Eio.Time.clock -\u003e\n ?config:config -\u003e\n unit -\u003e\n t\n\nval request : ?cancel:Cancel.t -\u003e t -\u003e request -\u003e (response, error) result\nval fetch : ?cancel:Cancel.t -\u003e t -\u003e request -\u003e (status * Headers.t * string, error) result\nval stream : ?cancel:Cancel.t -\u003e t -\u003e request -\u003e (status * Headers.t * Cstruct.t Stream.t, error) result\n\nval close_idle : t -\u003e unit\nval pool_stats : t -\u003e { active: int; idle: int; total: int }\n```\n\nFeatures:\n- Protocol selection (HTTP/1.1 vs HTTP/2) via ALPN or config\n- Connection pooling\n- Automatic redirect following\n- Compression handling\n- TLS with system certs by default","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-29T14:31:27.67982735+01:00","updated_at":"2025-12-29T17:00:20.730823454+01:00","closed_at":"2025-12-29T17:00:20.730823454+01:00","dependencies":[{"issue_id":"hcs-j2z","depends_on_id":"hcs-qnb","type":"parent-child","created_at":"2025-12-29T14:31:51.749045471+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-j2z","depends_on_id":"hcs-7n9","type":"blocks","created_at":"2025-12-29T14:31:54.365652586+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-j2z","depends_on_id":"hcs-d5s","type":"blocks","created_at":"2025-12-29T14:31:55.246269371+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-j2z","depends_on_id":"hcs-2ca","type":"blocks","created_at":"2025-12-29T14:31:55.835151512+01:00","created_by":"gdiazlo","metadata":"{}"}]}
111115{"id":"hcs-j5q","title":"Move Go benchmark server to dedicated folder (bench/comparison/go_fasthttp/)","status":"closed","priority":2,"issue_type":"chore","created_at":"2025-12-30T00:14:15.760072799+01:00","updated_at":"2025-12-30T00:17:18.571463212+01:00","closed_at":"2025-12-30T00:17:18.571463212+01:00"}
112116{"id":"hcs-j7fj","title":"Update: Migrate las.ml to new App API","description":"Update bin/las/las.ml to use new API:\n- Change Hcs.Endpoint → Hcs.App\n- Create Server.config separately for network settings\n- Pass both App.t and Server.config to App.start\n- Update README tutorial if needed\n\nThis is the only consumer of Endpoint.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-03T20:59:41.77709642+01:00","created_by":"gdiazlo","updated_at":"2026-01-03T21:11:13.189606663+01:00","closed_at":"2026-01-03T21:11:13.189606663+01:00","close_reason":"Superseded by expanded scope - adding router pipelines","dependencies":[{"issue_id":"hcs-j7fj","depends_on_id":"hcs-pcri","type":"blocks","created_at":"2026-01-03T21:00:17.847507496+01:00","created_by":"gdiazlo"},{"issue_id":"hcs-j7fj","depends_on_id":"hcs-1lvl","type":"parent-child","created_at":"2026-01-03T21:00:24.580564444+01:00","created_by":"gdiazlo"}]}
113117{"id":"hcs-j7j","title":"Implement Go/fasthttp benchmark server (plaintext + json, HTTP/1+2, CPU scaling)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-30T22:21:31.597229058+01:00","updated_at":"2025-12-30T22:28:28.338758567+01:00","closed_at":"2025-12-30T22:28:28.338758567+01:00"}
118118+{"id":"hcs-jbth","title":"CRITICAL: Add WebSocket Origin validation to prevent CSWSH attacks","status":"closed","priority":0,"issue_type":"bug","created_at":"2026-01-06T11:52:44.792884734+01:00","created_by":"gdiazlo","updated_at":"2026-01-06T12:03:35.132986095+01:00","closed_at":"2026-01-06T12:03:35.132986095+01:00","close_reason":"Added origin_policy type and validate_origin function to websocket.ml. Added ws_config to server.ml with origin_policy and max_payload_size. Server now validates Origin header before accepting WebSocket upgrades."}
114119{"id":"hcs-jk8","title":"WebSocket Benchmark: Memory and Connection Scaling","description":"Compare HCS (OCaml) vs Go vs Rust WebSocket implementations. Metrics: memory per connection, max connections per CPU.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-30T09:59:44.349580383+01:00","updated_at":"2025-12-30T10:23:00.707208406+01:00","closed_at":"2025-12-30T10:23:00.707208406+01:00"}
115120{"id":"hcs-jqx","title":"Cache :path header extraction in request_handler","description":"H2.Headers.get is O(n). For the :path pseudo-header which is always present and accessed for every request, consider direct access or caching.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T08:57:26.215703677+01:00","updated_at":"2025-12-30T09:01:43.754321197+01:00","closed_at":"2025-12-30T09:01:43.754321197+01:00","dependencies":[{"issue_id":"hcs-jqx","depends_on_id":"hcs-cq4","type":"parent-child","created_at":"2025-12-30T08:57:49.840282561+01:00","created_by":"gdiazlo","metadata":"{}"}]}
116121{"id":"hcs-jsl","title":"Implement Path DSL","description":"Implement type-safe path DSL in hcs-core/path.ml:\n\n```ocaml\ntype 'a t\n\n(* Combinators *)\nval root : unit t (* / *)\nval const : string -\u003e unit t (* /literal *)\nval str : string t (* /:param - captures string *)\nval int : int t (* /:param - captures int *)\nval int32 : int32 t\nval int64 : int64 t\nval uuid : string t (* validates UUID format *)\nval rest : string list t (* /** - captures remaining *)\n\nval ( / ) : 'a t -\u003e 'b t -\u003e ('a * 'b) t\nval ( /: ) : unit t -\u003e 'a t -\u003e 'a t (* const / capture shorthand *)\n\nval trailing_slash : 'a t -\u003e 'a t\n\n(* For router compilation *)\ntype segment =\n | Literal of string\n | Param_string\n | Param_int\n | Param_int32\n | Param_int64 \n | Param_uuid\n | Wildcard\n\nval to_segments : 'a t -\u003e segment list\nval parse : 'a t -\u003e string list -\u003e ('a, string) result\n```\n\nPure OCaml, uses GADTs for type safety.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-29T14:32:24.842727479+01:00","updated_at":"2025-12-29T14:56:33.544162475+01:00","closed_at":"2025-12-29T14:56:33.544162475+01:00","dependencies":[{"issue_id":"hcs-jsl","depends_on_id":"hcs-2ie","type":"parent-child","created_at":"2025-12-29T14:32:55.556666992+01:00","created_by":"gdiazlo","metadata":"{}"}]}
···176181{"id":"hcs-uzm","title":"Middleware redesign: add circuit breaker and retry middlewares","description":"Expose Control.ml patterns (circuit breaker, retry) as proper Eio middlewares in middleware_eio.ml. Keep both rate limiters as they serve different purposes (token bucket for clients, sliding window for servers).","status":"closed","priority":1,"issue_type":"feature","created_at":"2026-01-01T18:14:50.873049196+01:00","updated_at":"2026-01-01T18:17:42.278585485+01:00","closed_at":"2026-01-01T18:17:42.278585485+01:00"}
177182{"id":"hcs-v4al","title":"Implement: Router scopes with pipe_through","description":"Extend Router to support scoped routes with pipelines:\n\n```ocaml\nRouter.scope \"/api\" ~through:api_pipeline [\n Route.get \"/posts\" list_posts;\n Route.post \"/posts\" create_post;\n]\n\nRouter.scope \"/\" ~through:browser_pipeline [\n Route.get \"/\" home;\n Route.get \"/login\" login_form;\n]\n```\n\nWhen a route matches, its scope's pipeline runs before the handler.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-03T21:11:56.252334871+01:00","created_by":"gdiazlo","updated_at":"2026-01-03T21:30:55.732720684+01:00","closed_at":"2026-01-03T21:30:55.732720684+01:00","close_reason":"Implemented router scopes","dependencies":[{"issue_id":"hcs-v4al","depends_on_id":"hcs-1lvl","type":"parent-child","created_at":"2026-01-03T21:12:49.502773792+01:00","created_by":"gdiazlo"},{"issue_id":"hcs-v4al","depends_on_id":"hcs-uoki","type":"blocks","created_at":"2026-01-03T21:13:35.004673762+01:00","created_by":"gdiazlo"},{"issue_id":"hcs-v4al","depends_on_id":"hcs-ty6r","type":"blocks","created_at":"2026-01-03T21:13:50.176121606+01:00","created_by":"gdiazlo"}]}
178183{"id":"hcs-vjo","title":"docs: Installation guide","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-03T00:44:18.366102527+01:00","updated_at":"2026-01-03T00:48:23.81083899+01:00","closed_at":"2026-01-03T00:48:23.81083899+01:00","dependencies":[{"issue_id":"hcs-vjo","depends_on_id":"hcs-0bi","type":"blocks","created_at":"2026-01-03T00:45:24.304083004+01:00","created_by":"gdiazlo","metadata":"{}"}]}
184184+{"id":"hcs-vm1i","title":"CRITICAL: Enforce max payload size limit in WebSocket frame parsing","status":"closed","priority":0,"issue_type":"bug","created_at":"2026-01-06T11:52:46.126792557+01:00","created_by":"gdiazlo","updated_at":"2026-01-06T12:00:46.604649527+01:00","closed_at":"2026-01-06T12:00:46.604652187+01:00"}
179185{"id":"hcs-vwmd","title":"docs: PubSub guide","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-03T00:44:56.162777901+01:00","updated_at":"2026-01-03T01:03:33.230785198+01:00","closed_at":"2026-01-03T01:03:33.230785198+01:00"}
180186{"id":"hcs-w0w","title":"LAS: Authentication module (auth.ml)","description":"Password hashing, current_user helper using Session, require_auth middleware, login/logout functions.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-01T23:41:37.261591945+01:00","updated_at":"2026-01-02T00:15:18.196756733+01:00","closed_at":"2026-01-02T00:15:18.196756733+01:00","dependencies":[{"issue_id":"hcs-w0w","depends_on_id":"hcs-62k","type":"parent-child","created_at":"2026-01-01T23:42:33.336368591+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-w0w","depends_on_id":"hcs-gii","type":"blocks","created_at":"2026-01-01T23:43:13.641056385+01:00","created_by":"gdiazlo","metadata":"{}"}]}
181187{"id":"hcs-w1c","title":"Create HCS WebSocket benchmark server","description":"OCaml server using lib/websocket.ml. Accept connections, keep alive with ping/pong, report connection count. Port configurable via CLI.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-30T09:59:57.95619465+01:00","updated_at":"2025-12-30T10:03:58.03114584+01:00","closed_at":"2025-12-30T10:03:58.03114584+01:00","dependencies":[{"issue_id":"hcs-w1c","depends_on_id":"hcs-jk8","type":"parent-child","created_at":"2025-12-30T10:00:25.560665813+01:00","created_by":"gdiazlo","metadata":"{}"}]}
···188194{"id":"hcs-y4ra","title":"Test: Verify all tests pass after refactor","description":"Run full test suite:\n- dune build\n- dune test\n- Manual test of las application\n- Verify hs (file server) still works (doesn't use Endpoint)","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-03T20:59:48.153343384+01:00","created_by":"gdiazlo","updated_at":"2026-01-03T21:11:28.352189828+01:00","closed_at":"2026-01-03T21:11:28.352189828+01:00","close_reason":"Superseded by expanded scope - adding router pipelines","dependencies":[{"issue_id":"hcs-y4ra","depends_on_id":"hcs-j7fj","type":"blocks","created_at":"2026-01-03T21:00:38.071975277+01:00","created_by":"gdiazlo"},{"issue_id":"hcs-y4ra","depends_on_id":"hcs-1lvl","type":"parent-child","created_at":"2026-01-03T21:00:39.745458479+01:00","created_by":"gdiazlo"},{"issue_id":"hcs-y4ra","depends_on_id":"hcs-lskj","type":"blocks","created_at":"2026-01-03T21:00:43.127315881+01:00","created_by":"gdiazlo"}]}
189195{"id":"hcs-y5a","title":"LAS: Data models (models.ml)","description":"Define types for user, link, vote, comment. Include JSON serialization helpers.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-01T23:41:27.179866273+01:00","updated_at":"2026-01-01T23:50:41.86681997+01:00","closed_at":"2026-01-01T23:50:41.86681997+01:00","dependencies":[{"issue_id":"hcs-y5a","depends_on_id":"hcs-62k","type":"parent-child","created_at":"2026-01-01T23:42:23.256823169+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-y5a","depends_on_id":"hcs-dpu","type":"blocks","created_at":"2026-01-01T23:43:03.557959162+01:00","created_by":"gdiazlo","metadata":"{}"}]}
190196{"id":"hcs-y9w","title":"TLS Configuration","description":"Implement Tls_config module for client and server TLS configuration with verification modes and system certificate loading.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-29T14:25:24.911800471+01:00","updated_at":"2025-12-29T15:25:06.384359847+01:00","closed_at":"2025-12-29T15:25:06.384359847+01:00","dependencies":[{"issue_id":"hcs-y9w","depends_on_id":"hcs-zba","type":"parent-child","created_at":"2025-12-29T14:26:05.906211432+01:00","created_by":"gdiazlo","metadata":"{}"}]}
197197+{"id":"hcs-ya52","title":"HIGH: Enforce max_body_size and max_header_size configuration limits","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-06T11:52:47.738430386+01:00","created_by":"gdiazlo","updated_at":"2026-01-06T12:06:57.021596603+01:00","closed_at":"2026-01-06T12:06:57.021596603+01:00","close_reason":"Added max_body_size enforcement in H1_handler.handle and H1_handler.handle_direct. Server now rejects requests with 413 Payload Too Large when body exceeds config.max_body_size."}
191198{"id":"hcs-yg6","title":"LAS: Request handlers (handlers.ml)","description":"Handlers for index, show_link, create_link, vote, login, logout, register. Use Plug.Negotiate.respond for dual JSON/HTML.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-01T23:41:52.385545141+01:00","updated_at":"2026-01-02T10:23:27.072133297+01:00","closed_at":"2026-01-02T10:23:27.072133297+01:00","dependencies":[{"issue_id":"hcs-yg6","depends_on_id":"hcs-62k","type":"parent-child","created_at":"2026-01-01T23:42:48.451290008+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-yg6","depends_on_id":"hcs-gii","type":"blocks","created_at":"2026-01-01T23:43:23.721075403+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-yg6","depends_on_id":"hcs-w0w","type":"blocks","created_at":"2026-01-01T23:43:28.763639466+01:00","created_by":"gdiazlo","metadata":"{}"},{"issue_id":"hcs-yg6","depends_on_id":"hcs-pod","type":"blocks","created_at":"2026-01-01T23:43:33.804311531+01:00","created_by":"gdiazlo","metadata":"{}"}]}
192199{"id":"hcs-yhar","title":"Release: Bump version to 0.2.0","description":"Final release tasks:\n\n1. Update dune-project version 0.1.1 → 0.2.0\n2. Regenerate hcs.opam\n3. Final review of CHANGELOG\n4. Create git tag v0.2.0\n5. Push to remote","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-03T21:12:18.944912994+01:00","created_by":"gdiazlo","updated_at":"2026-01-03T21:31:26.067799605+01:00","closed_at":"2026-01-03T21:31:26.067799605+01:00","close_reason":"Version bumped to 0.2.0","dependencies":[{"issue_id":"hcs-yhar","depends_on_id":"hcs-1lvl","type":"parent-child","created_at":"2026-01-03T21:13:24.89058491+01:00","created_by":"gdiazlo"},{"issue_id":"hcs-yhar","depends_on_id":"hcs-lsmn","type":"blocks","created_at":"2026-01-03T21:15:31.093477697+01:00","created_by":"gdiazlo"}]}
193200{"id":"hcs-yppn","title":"Design: Define App module interface","description":"Design the new App module interface:\n- App.config: secret_key_base, health_check (app-level only)\n- App.t: config, plugs, router, ws_handler\n- App.create: takes App.config\n- App.start: takes App.t, Server.config, and env\n- Remove all server-level config (port, bind, domains, protocol, tls) from App\n\nDeliverable: Type signatures and interface documentation","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-03T20:59:33.999218536+01:00","created_by":"gdiazlo","updated_at":"2026-01-03T21:10:58.025296424+01:00","closed_at":"2026-01-03T21:10:58.025296424+01:00","close_reason":"Superseded by expanded scope - adding router pipelines","dependencies":[{"issue_id":"hcs-yppn","depends_on_id":"hcs-1lvl","type":"parent-child","created_at":"2026-01-03T21:00:09.419619431+01:00","created_by":"gdiazlo"}]}