Implement the R-1 adapter (FT-WP-0001 T05/T09); mark workplans blocked
Builds internal/adapter and cmd/adapter: the three contracts/r1.openapi.yaml operations, idempotency on post_id, the reviewed_by/consent-basis refusals, per-form (R-2/R-3) length limits, and Markdown-to-Telegram rendering, all against a Sender interface so it's testable without a live bot token. Every other open task in FT-WP-0001 and FT-WP-0002 needs something this repo can't supply on its own: the human session bootstrap in FT-WP-0002 T01, the fluid CLI from fluid-core, or a person's judgment (consent basis, editorial review, publishing pace). Set both workplans to status: blocked and flagged FT-WP-0002-T01 needs_human on the hub, since it's the single blocker gating everything else. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 278411@bnt-lap001 Assistant-Session: 19568045-15bc-4b88-ba3d-8e95b4f9c6f1
This commit is contained in:
parent
f7f5302903
commit
bfebca3aee
10 changed files with 1052 additions and 6 deletions
46
internal/adapter/telemetry.go
Normal file
46
internal/adapter/telemetry.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package adapter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HTTPTelemetry POSTs to the control plane, per docs/adapter-contract.md.
|
||||
// It must never carry subscriber identity or post body text; callers control
|
||||
// that by what they put in fields.
|
||||
type HTTPTelemetry struct {
|
||||
ControlURL string
|
||||
hc *http.Client
|
||||
}
|
||||
|
||||
// NewHTTPTelemetry builds a telemetry emitter posting to
|
||||
// <controlURL>/control/v1/telemetry.
|
||||
func NewHTTPTelemetry(controlURL string) *HTTPTelemetry {
|
||||
return &HTTPTelemetry{ControlURL: controlURL, hc: &http.Client{Timeout: 10 * time.Second}}
|
||||
}
|
||||
|
||||
func (t *HTTPTelemetry) Emit(ctx context.Context, event string, fields map[string]any) {
|
||||
if t.ControlURL == "" {
|
||||
return
|
||||
}
|
||||
payload := map[string]any{"event": event, "fields": fields}
|
||||
body, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, t.ControlURL+"/control/v1/telemetry", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
// Best-effort: a dropped telemetry event must never fail the publication
|
||||
// it describes.
|
||||
resp, err := t.hc.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = resp.Body.Close()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue