8000 Tags · manisrinivasan2k1/monid · GitHub
[go: up one dir, main page]

Skip to content

Tags

Tags

catalog-v0.0.4

Toggle catalog-v0.0.4's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat(magic-hour): add AI GIF connector (monid-ai#56)

* feat(magic-hour): add AI GIF connector

* fix(magic-hour): settle credits only on completion

* test(magic-hour): cover AI GIF lifecycle with fixtures

* test(magic-hour): mark replay fixtures synthetic

* test(magic-hour): record the happy chain, cover canceled/unknown status, input gate and live run

- recorded-job-succeeded.json replaces the synthetic happy chain: a real
  `deno task record` run (2026-09-25), minimized to submit + one rendering
  tick + complete, signed download query stripped.
- The synthetic chains now use the recorded body shapes (submit
  {id, frame_cost, credits_charged}; full project object; error object).
- New chains: canceled -> 409 zero usage; an unrecognized status keeps
  polling until complete.
- New tests: an omitted output_format goes on the wire as "gif"; the input
  schema rejects an over-500 prompt, an empty prompt, an unknown format and
  an unknown key before any upstream call; a gated live test.

---------

Co-authored-by: Octo Dang <ooctoo@monid.ai>

catalog-v0.0.3

Toggle catalog-v0.0.3's commit message

Verified

This commit was signed with the committer’s verified signature.
FeiyouG Feiyou Guo
Merge branch 'main' into feat/enable-catalog-publish-trigger

catalog-v0.0.2

Toggle catalog-v0.0.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Resource lifecycle, 2/2 — saperly connector (17 endpoints + phone-num…

…ber resource) (monid-ai#37)

* feat(platform): resource lifecycle — schema, compiler, engine, local host loop (1/2)

The RESOURCE family: first-class support for durable, billable things a
provider can OWN on a workspace's behalf (openspec:
add-resource-lifecycle-saperly D30–D37, refined by refine-resource-model
D38–D47). Platform half of a stacked pair — 2/2 adds the saperly proving
connector.

- resource defs (slug, data, REQUIRED usage rate card: one period clock
  + fixed/estimated lines, reconcileUsage per estimated line, lifecycle
  verify/release/refresh, views, webhooks) compiled to zResourceDoc and
  executed via engine.loadResource
- purpose-keyed endpoint bindings (provisions ≤1 / uses / updates /
  releases / reads): ownership pre-gate in canonical order, uniform
  vendor-shaped 404 on foreign ids, gated instances injected as
  data.resources[alias], settle marks by purpose, ensure seeds persist
  pre-run
- mid-run metering = the estimate re-run (zEstimateData.elapsedMs?,
  usage.updateEstimateEveryMs); stop() outcomes (COMPLETED / UNRESOLVED
  / STOPPED_UNSETTLED); run.runId, bounded utils.sleep
- webhooks: positional scope, declarative HMAC verify (payload template
  must contain ${rawBody}), ONE route(delivery) → {who, what} verdict
- identity guard: connectors/ids.lock.json + deno task ids:check
  (endpoint ids stay derived ?? request.path — the lock turns silent
  drift into CI failure)
- local host loop: Deno KV IResourceStore (.output/local.db) as
  engine:run's default ownership window; scripts/webhook.ts
  simulate|listen (sign/verify/route per compiled descriptors;
  cloudflared/tailscale/none tunnels, scripts-only)
- engine 0.4.0 (resources_since 0.4.0); error taxonomy:
  NO_RESOURCE_READER, RESOURCES_UNDECLARED, PROVISION_CONSTRUCT,
  RESOURCE_OP_FAILED

* feat(connectors): saperly — 17 endpoints + the phone-number resource (2/2)

The resource lifecycle's proving connector (part 2/2; the platform is
1/2). Real US phone numbers with AI personas answering and placing
calls.

- resource saperly/phone-number: $2/month fixed rent (MONTH/1,
  CREATION_TIME anchor — flat, confirmed vs the live OpenAPI: no
  proration/refunds); lifecycle verify (404/releasedAt ⇒ inactive,
  flaky reads throw retriable) / release (idempotent, embedded
  connection dies with the number) / refresh (connection pointer
  AUTHORITATIVE — absence upstream clears it); live connection view
  sanitized through an allowlist
- numbers: provision (consent-priced saga with ONE 409 PriceChanged
  re-quote retry; seed carries the quoted observedUsage.rent), get,
  list, update (persona edit), sync (webhook re-sync), release
- calls: place (estimate 60s floor / elapsed-priced,
  updateEstimateEveryMs 30s; stop hangs up then drains), get, list,
  inbound (webhook-admitted, admit-overdraft), transcripts, recordings
- messages: send, list, inbound (bill-only); catalogs: voices,
  languages
- ONE webhook stream (number-events): HMAC verify descriptor + route
  verdict (message.received → run inbound-messages; call.received →
  run inbound-calls; call.completed/recording.saved → signal-run;
  number.* → refresh; receipts → ignore)
- categories: agentic-phone + sms leaves; ids.lock +17 endpoints
  +1 resource
- 21 recorded/synthetic fixtures; provider-level strip of internal
  keys on success AND error surfaces

* review(platform): address CodeRabbit round 1

Bugs:
- ensure() binds utils to the DERIVED input — utils.request() now sends
  post-toRequest body/query consistent with the derived URL (ctx.data
  keeps the validated input, the fn-facing contract)
- reader window normalizes host failures: only RESOURCE_OP_FAILED
  rethrows; any other reader throw wraps retriable (a host reusing
  INVALID_INPUT must not mark a transient read non-retriable)
- KvResourceStore transitions are atomic: provision/release are one
  kv.atomic() each (row + tombstone together); refresh checks the read
  versionstamp so a concurrent release wins
- webhook --execute uses the same host ordering as engine:run (admit
  seeds pre-start, persist provisions/releases post-settle)

Tightenings:
- EngineCtx.admit — the seed ADMISSION port: run() hands ensure's seeds
  to the host's write before start() (absent + seeds ⇒ loud warn, never
  a silent drop); scripts pass a store-backed admit via shared
  admitInto/persistEffects helpers
- verify.payload template must ALSO contain ${timestamp} — freshness
  bound to the HMAC (unbound, a captured body+signature replays forever
  inside rolling toleranceMs windows); saperly already complies
- version-check CONTRACT_PATHS: dead billing.ts/accrue.ts out,
  resource/usage.ts + resource/def.ts in
- resource ids.ts comment: identity is AUTHORED (slug) + asserted, not
  inferred; .coderabbit.yaml reviews stacked-base PRs (base_branches)

Spec drift (both change folders now read the final API):
- add-resource-lifecycle-saperly specs/tasks: OwnedResource,
  data.resource, verify/release/refresh/reconcileUsage/view,
  accrued(runInput, elapsedMs), host-driven ensure + admit port
- run identity: SPEC aligned to code (host handle = stable; run() mints
  ONE UUID per loop; direct phase calls without a handle are per-call —
  by design, not persisted state)
- refine-resource-model proposal/compiler spec: endpoint: stays optional
  (the revert's missed spots); 'four write methods' → the five verbs
- minimax test files restored to main's bytes (pure fmt churn, out of
  the PR)

Deferred: resource-scope webhook simulate/listen — no resource-scope
hook exists in-tree yet (saperly defers subscribe); noted in the script
header.

Post-merge version reconcile: main took 0.4.0 (credential overhaul) —
the resource family ships at 0.5.0 (resources_since 0.5.0).

* review(saperly): address CodeRabbit round 1 on monid-ai#37

Paid-number containment — never delete a maybe-bound connection:
- provision-numbers: an AMBIGUOUS bind failure (5xx / thrown transport)
  now RECONCILES against the number record before any cleanup — our
  connection attached ⇒ treated as bound (the failure lied); shown
  definitively unbound ⇒ orphan deleted; inconclusive ⇒ connection KEPT
  (a leaked free connection beats a dangling pointer). Clean 4xx stays
  a definitive rejection. New fixture arm pins the reconciled-as-bound
  path; the degraded fixture gains the reconcile read.
- update-numbers: same reconcile on the repair bind — the repair-bind
  Idempotency-Key makes RETRYING safe, not deleting; delete only when
  the number record proves the bind did not commit (new
  update-repair-ambiguous fixture: 500 that committed ⇒ bound, no
  delete).
- a 2xx purchase with no readable id now deletes the pre-created
  connection before seed throws PROVISION_CONSTRUCT (the alarm stands,
  the orphan doesn't).

Webhook route:
- the generic `id` fallback is now scoped: number.* events correlate
  to the RESOURCE via numberId ?? id (who and what agree), call.* keeps
  the call-scoped fallback — a number.deleted carrying only `id` no
  longer misroutes as a run signal. Test pin added.

Contract fidelity + hygiene:
- zConnectionPatchInput: .refine at-least-one → z.union of .required()
  arms (the contactout pattern) — the published update contract now
  rejects {} post-compilation too
- zCountry loses its shared-schema .default; the "US" default moves to
  the two binding sites (house rule: our tightenings live at bindings;
  compiled docs unchanged)
- provider categories gain "sms" (the three message endpoints already
  declare it); rate card cited once in the provider header and once
  above the test rate pins (saperly.com/docs/pricing, confirmed
  2026-09-16)

* fix(webhooks): verify.signaturePrefix — a vendor may sign `<prefix><hex>`

Some vendors put literal text before the hex digest in the signature
header (saperly: `v1=<hex>`). The verify descriptor had no way to say
so and checkDelivery compared bare hex, so such a delivery could only
fail "signature mismatch" while simulate's own bare-hex signing kept
the local loop green.

- zWebhookVerify: optional `signaturePrefix` (absent = bare hex,
  unchanged for every existing hook)
- scripts/webhook.ts: sign() emits it, checkDelivery() requires it

* fix(saperly): number-events verify — signaturePrefix "v1="

Saperly's signature header is `v1=<hex>`
(https://saperly.com/docs/guides/webhooks; v1's
adaptors/saperly/webhooks.ts strips the same prefix). Without the
prefix declared every real delivery fails "signature mismatch".

Checked with `webhook listen saperly`: a vendor-style `v1=` delivery
was 401 before, 200 after; bare hex is now 401.

* test(webhook): pin the verify executor; signature-first, constant-time (v1 fidelity)

The signaturePrefix fix (29af387/62dbab5) rested on a manual `listen`
check — the executor had NO unit pins, which is exactly how the bare-hex
port bug hid (simulate signed and verified with the same wrong
assumption, a self-consistent loop). Now:

- sign/checkDelivery exported (CLI behind import.meta.main so the test
  import doesn't parse the runner's args); scripts/webhook.test.ts pins
  the v1 semantics: prefixed round-trip verifies; bare-hex vs declared
  prefix ⇒ mismatch; prefixed vs undeclared ⇒ mismatch; tampered raw
  bytes ⇒ mismatch
- checkDelivery now checks the SIGNATURE FIRST with a constant-time
  comparison, THEN the tolerance window — v1's documented ordering
  (adaptors/saperly/webhooks.ts): timing/reason must not distinguish a
  stale-but-valid signature from a fresh-but-invalid one. Both orderings
  pinned.
- connector-schema spec: verify MAY declare signaturePrefix (absent =
  bare hex; a header missing a declared prefix is a mismatch);
  verification is signature-first, constant-time.

* review(round-2): trust-boundary invariants, provider cadence, slot shapes

Doc schemas now RE-ENFORCE what the authoring schemas enforced — a
compiled doc crosses a trust boundary (disk, hosts), so a doctored
artifact must fail LOAD, never silently degrade mid-run:
- bundle: a resource doc's id <provider>/ prefix must equal
  doc.provider (execution fuses doc.provider's auth+origin while hosts
  select by id — a mismatch runs one vendor's resource under another's
  identity)
- endpoint docs: the binding invariants (provisions ≤1, as requires
  key, alias uniqueness) extracted into ONE shared checker applied by
  BOTH the def and doc superRefines — link.ts can no longer silently
  run provisions[0] of a doctored two-provisions doc
- resource docs: reconcile coherence refined on the doc (reconciler
  keys === estimated-line keys, both directions) — a fixed-line
  reconciler fails load instead of surfacing as NOT_ASYNC at call time

usage.updateEstimateEveryMs now resolves endpoint ?? provider (the
layering every other usage leaf follows; the spec always promised it) —
a provider-declared cadence previously VANISHED from compiled docs and
the engine treated affected metered runs as static: holds never
re-priced. Used in the coherence checks, the version floor, and the
emitted doc.

The inputs ⊇ slot check now lints SHAPES, not just names: a
slot-required property whose declared scalar type mismatches fails
compilation (id: number no longer satisfies id: string), one level of
nested required recursed. Bounded lint, not JSON-Schema subsumption.

Also: runner.ts loadResource comment → the real op names. Pins: six new
tests (three trust-boundary, two cadence, one slot-type).

* docs(review): round-2 drift — openspec to final API, synthetic fixtures

- add-resource-lifecycle-saperly design.md + proposal.md carry the
  AMENDED-by-refine banner (the D30–D37 narrative stays; the vocabulary
  mapping is stated once) — EXCEPT the versioning claim, corrected
  outright: doc_format_since/fn_abi_since stay put, resources_since
  alone carries the family
- its four spec deltas state the FINAL contracts: purpose-keyed binding
  arrays + shape lint (compiler), usage rate card + slug + doc-side
  coherence (schema), loadResource verify/view/reconcileUsage
  (testing), the shipped phone-number fields (saperly)
- refine design: estimate(input, elapsedMs) — the real signature
- ALL saperly fixtures renamed synthetic-* (every one is hand-built —
  no saperly key was ever used) + fixture() refs updated
- narration comments dropped (schema/common ×3, catalog JSDoc,
  webhook.test ×3)
- .coderabbit.yaml fixtures rule updated to the shipped allowlist
  mechanism: response headers only from RECORDED_RES_HEADERS (location)

---------

Co-authored-by: ZuoyouDang <ooctoo@g.ucla.edu>

pre-split-37

Toggle pre-split-37's commit message

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
revert(identity): endpoint: optional again — derivation is the defaul…

…t, ids.lock guards renames

The required-endpoint: rule (D45's second arm) taxed every def and forced
a 230-file mechanical sweep — including all 183 defs of main's new
connectors, which this branch had no business touching. The default
(request.path, trailing slashes stripped) is reasonable, and the rename
protection it bought is already covered: connectors/ids.lock.json turns
a derived-id drift (a vendor moving a route) into a CI failure.

- endpoint: back to zEndpointPath.optional(); compiler derivation
  (?? request.path) restored
- 230 sweep-inserted endpoint: lines removed (the 104 meaningful
  declarations and main's 3 deliberate redundant ones stay); contextdev
  and the other 8 merge connectors are byte-for-byte main again
- 35 test-def insertions removed; .coderabbit.yaml + CI workflows +
  README restored to main's bytes (repo-wide fmt noise)
- docs + openspec amended (D45, connector-schema spec, tasks 5.1,
  ids-check header); resource slug stays REQUIRED; ids.lock stays
- all 338 compiled docs verified byte-identical

catalog-v0.0.1

Toggle catalog-v0.0.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore(publish): disable GitLab trigger until MR 258; record artifact-…

…store rationale (monid-ai#4)

- publish-catalog.yml: GitLab trigger step commented out — until the
  monid-services catalog-publish job + catalog_publish_tag pipeline input
  land, the curl would fail after the release is already created. A
  publish now stops at the GitHub Release (the durable artifact); once
  re-enabled, re-run an already-published tag's workflow to ingest it
  (every step is idempotent).
- DEVELOPMENT.md: note the disabled trigger + record why publishing is
  tag-triggered and why the release asset is the artifact store (vs
  release-triggered / Actions artifacts / direct-to-S3).
0