This commit is contained in:
2025-05-01 15:39:20 +00:00
parent a59ebd6202
commit 09aadc702e
7 changed files with 145 additions and 130 deletions

View File

@ -1,31 +1,26 @@
## Plan: Integrate @push.rocks/smartacme into Port80Handler
## Plan: Centralize Certificate Renewal for all certificates
- [x] read the complete README of @push.rocks/smartacme and understand the API.
- [x] Add imports to ts/plugins.ts:
- import * as smartacme from '@push.rocks/smartacme';
- export { smartacme };
- [x] In Port80Handler.start():
- Instantiate SmartAcme and use the in memory certmanager.
- use the DisklessHttp01Handler implemented in classes.port80handler.ts
- Call `await smartAcme.start()` before binding HTTP server.
- [x] Replace old ACME flow in `obtainCertificate()` to use `await smartAcme.getCertificateForDomain(domain)` and process returned cert object. Remove old code.
- [x] Update `handleRequest()` to let DisklessHttp01Handler serve challenges.
- [x] Remove legacy methods: `getAcmeClient()`, `handleAcmeChallenge()`, `processAuthorizations()`, and related token bookkeeping in domainInfo.
## Plan: Certificate Provider Hook & Observable Emission
- [x] Extend IPortProxySettings (ts/smartproxy/classes.pp.interfaces.ts):
- Define type ISmartProxyCertProvisionObject = tsclass.network.ICert | 'http01'`.
- Add optional `certProvider?: (domain: string) => Promise<ISmartProxyCertProvisionObject>`.
- [x] Enhance SmartProxy (ts/smartproxy/classes.smartproxy.ts):
- Import `EventEmitter` and change class signature to `export class SmartProxy extends EventEmitter`.
- Call `super()` in constructor.
- In `initializePort80Handler` and `updateDomainConfigs`, for each non-wildcard domain:
- Invoke `certProvider(domain)` if provided, defaulting to `'http01'`.
- If result is `'http01'`, register domain with `Port80Handler` for ACME challenges.
- If static cert returned, bypass `Port80Handler`, apply via `NetworkProxyBridge`
- Subscribe to `Port80HandlerEvents.CERTIFICATE_ISSUED` and `CERTIFICATE_RENEWED` and re-emit on `SmartProxy` as `'certificate'` events (include `domain`, `publicKey`, `privateKey`, `expiryDate`, `source: 'http01'`, `isRenewal` flag).
- [x] Extend NetworkProxyBridge (ts/smartproxy/classes.pp.networkproxybridge.ts):
- Add public method `applyExternalCertificate(data: ICertificateData): void` to forward static certs into `NetworkProxy`.
- [ ] Define `SmartProxy` `'certificate'` event interface in TypeScript and update documentation.
- [ ] Update README with usage examples showing `certProvider` callback and listening for `'certificate'` events.
- [ ] 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