## Plan: Centralize Certificate Renewal for all certificates - [ ] Remove renewal logic from Port80Handler - Delete `startRenewalTimer()` and `checkForRenewals()` methods - Remove `renewThresholdDays` and `renewCheckIntervalHours` options from `IPort80HandlerOptions` - [ ] Expose certificate status from Port80Handler - Ensure `getDomainCertificateStatus()` returns `{certObtained, expiryDate}` for each domain - [ ] Add renewal settings to SmartProxy - Extend `port80HandlerConfig` to include `renewThresholdDays` and `renewCheckIntervalHours` - [ ] Implement renewal scheduler in SmartProxy using taskbuffer - Add dependency on `@push.rocks/taskbuffer` and import `{ Task, TaskManager }` in `SmartProxy` - Add `performRenewals()` to iterate domains and trigger renewals where `daysRemaining <= renewThresholdDays` - Instantiate a `TaskManager` and define a `Task` that wraps `performRenewals()` - Use `taskManager.addAndScheduleTask(task, cronExpr)` to schedule renewals, building `cronExpr` from `renewCheckIntervalHours` (e.g. `0 0 */${renewCheckIntervalHours} * * *`) - Call `taskManager.start()` in `SmartProxy.start()` - [ ] Clean shutdown handling - Call `taskManager.stop()` in `SmartProxy.stop()` alongside other cleanup - [ ] Throttling and safety - Skip domains already in `obtainingInProgress` - Optionally batch or stagger renewal calls for large domain sets - [ ] Tests - Unit test `performRenewals()`, mocking `getDomainCertificateStatus()` to simulate expiring certificates - Integration test using an in-memory `Port80Handler` to verify that scheduled renewals invoke `obtainCertificate()` correctly - [ ] Documentation - Update `readme.plan.md` (this section) - Update `README.md` and code comments to document new renewal settings and workflow