Skip to content

Releases: objectstack-ai/objectstack

@objectstack/connector-rest@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:25
f55be04

Patch Changes

@objectstack/connector-openapi@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:25
f55be04

Minor Changes

  • 41e703b: feat(connector-openapi): degrade + retry on an unreachable remote spec URL (#3049 follow-up)

    The openapi provider fetches providerConfig.spec when it is an http(s) URL.
    That fetch previously threw plain on any failure, so a momentarily-unreachable
    spec endpoint aborted the whole app boot. It now classifies the fault the same
    way connector-mcp classifies its connect path (ADR-0097):

    • Network error (DNS / connection refused / timeout) or a transient HTTP
      status
      (408 / 429 / 5xx, mirroring the retryableStatusCodes
      convention) throws ConnectorUpstreamUnavailableError — the materializer
      degrades the instance (state: 'degraded' on GET /connectors, dispatch
      fails clearly) and retries with backoff plus on every metadata:reloaded.
    • A wrong URL (non-retryable 4xx) or an unparseable document stays a
      plain, fatal configuration fault.

    Inline and file-path (#3016) specs do no boot I/O and are unaffected.

Patch Changes

@objectstack/connector-mcp@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:25
f55be04

Patch Changes

@objectstack/cloud-connection@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:25
f55be04

Patch Changes

@objectstack/client@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:25
f55be04

Minor Changes

  • 9ccd1e9: feat(client): typed data.batchTransaction() for the atomic cross-object batch (#1604 / ADR-0034 item 4)

    Adds client.data.batchTransaction(operations) (and the environment-scoped
    client.project(id).data.batchTransaction) — a typed SDK surface for
    POST {basePath}/batch, the all-or-nothing cross-object transactional batch
    that master-detail saves go through. Reuses CrossObjectBatchOperation /
    CrossObjectBatchRequest / CrossObjectBatchResponse from
    @objectstack/spec/api (also re-exported from the client for convenience);
    supports { $ref: <opIndex> } intra-batch parent references.

    The method is always atomic and deliberately exposes no atomic flag — the
    endpoint rejects atomic: false with 400 BATCH_NOT_ATOMIC. Non-atomic
    per-object bulk writes stay on data.batch() / createMany / updateMany,
    so any best-effort fallback is isolated in the caller's adapter (the ObjectUI
    masterDetailTx adapter), not in the SDK.

  • bfa3c3f: Broadcast a transactionalBatch capability bit in discovery so clients negotiate the atomic cross-object batch declaratively, instead of runtime-probing 404/405/501 (#3298).

    The atomic cross-object batch endpoint (POST {basePath}/batch, #1604 / ADR-0034 item 4) and its typed SDK surface (client.data.batchTransaction, #3271) already shipped, but discovery never told a client whether a backend actually supports it. Consumers (notably ObjectUI's ObjectStackAdapter) had to probe: fire a /batch, read 404/405 (no route) or 501 (no runtime transaction), and only then fall back to non-atomic client-side simulation. That is "find out by calling", not capability negotiation — it cannot be decided at connect time and cannot serve as the "minimum backend supports /batch" gate that blocks hard-deleting the non-atomic fallback downstream.

    WellKnownCapabilitiesSchema gains a required transactionalBatch: boolean, and every discovery producer fills it honestly (declared === enforced), so it never becomes a declared-but-unpopulated bit:

    • @objectstack/metadata-protocol (getDiscovery) — reports whether the runtime engine can honour a transaction (typeof engine.transaction === 'function'). The /batch handler runs its ops inside engine.transaction(), which degrades to a non-atomic passthrough (or 501) without one.
    • @objectstack/rest (/discovery) — ANDs the engine signal with whether it actually mounts the route (api.enableBatch), so a server with batch disabled reports false even on a transaction-capable engine (never advertise an endpoint that would 404).
    • @objectstack/plugin-hono-server (standalone discovery) — reports false: this minimal surface registers CRUD only and does not mount /batch (that ships with @objectstack/rest). Under-reporting is the safe direction — a client keeps its correct-but-slower fallback rather than losing atomicity.
    • @objectstack/client — already normalizes hierarchical capabilities to flat booleans, so client.capabilities.transactionalBatch is exposed (and now typed) for declarative consumers.

    The bit follows the existing capability semantics: true ⟺ the /batch route is mounted and the runtime can honour a transaction — the exact condition under which the endpoint returns 200 rather than 404/405/501. Additive and behavior-preserving; only the discovery payload gains a field.

  • 668dd17: Breaking (npm type surface): retire the vestigial feed contracts + protocol surface (ADR-0052 §5 follow-up, #1959).

    The service-feed runtime was deleted in #1955; sys_comment / sys_activity
    are the canonical record-collaboration/timeline backend. This removes the dead
    type surface that still pointed at the deleted runtime — every removed method was
    already unreachable (the feed REST route was never mounted → 404; the protocol
    implementation was never wired with a feed service, so requireFeedService()
    could only throw). No behavior changes.

    No authorable metadata key is removed (the feeds: object capability flag and
    the RecordActivity UI component config are unchanged), so PROTOCOL_MAJOR
    stays 15 and this ships as minor rather than a protocol major.

    FROM → TO migration for every removed export:

    • @objectstack/spec/contractsIFeedService, CreateFeedItemInput,
      UpdateFeedItemInput, ListFeedOptions, FeedListResultremoved, no
      replacement
      . Comments/activity are plain records: write sys_comment / read
      sys_activity via the data engine or the REST data API.
    • @objectstack/spec/apiFeedApiContracts, FeedApiErrorCode,
      FeedProtocol, and all feed request/response schemas + types (GetFeed*,
      CreateFeedItem*, UpdateFeedItem*, DeleteFeedItem*, AddReaction*,
      RemoveReaction*, PinFeedItem*, UnpinFeedItem*, StarFeedItem*,
      UnstarFeedItem*, SearchFeed*, GetChangelog*, ChangelogEntry,
      SubscribeRequest/Response, FeedUnsubscribeRequest, UnsubscribeResponse,
      FeedPathParams, FeedItemPathParams, FeedListFilterType) → removed. Use
      the data API against sys_comment / sys_activity (/api/v1/data/sys_comment/…);
      reactions and threaded replies are fields on sys_comment.
    • @objectstack/spec/dataFeedItemSchema/FeedItem, FeedActorSchema/FeedActor,
      MentionSchema/Mention, ReactionSchema/Reaction,
      FieldChangeEntrySchema/FieldChangeEntry, FeedVisibility,
      RecordSubscriptionSchema/RecordSubscription, SubscriptionEventType, and the
      data-namespace NotificationChannelremoved. FeedItemType and
      FeedFilterMode are kept (live UI activity-timeline config). For notification
      channels use NotificationChannelSchema from @objectstack/spec/system.
    • @objectstack/clientclient.feed.* (list / create / update / delete /
      addReaction / removeReaction / pin / unpin / star / unstar / search /
      getChangelog / subscribe / unsubscribe) and the re-exported feed response
      types → removed. One-line fix: use client.data.* on sys_comment /
      sys_activity, e.g. client.data.create('sys_comment', { object, record_id, body })
      and client.data.find('sys_activity', { filters: [['record_id', '=', id]] }).
    • @objectstack/metadata-protocolObjectStackProtocolImplementation no longer
      implements the 14 feed methods; its constructor
      (engine, getServicesRegistry?, getFeedService?, environmentId?) becomes
      (engine, getServicesRegistry?, environmentId?). One-line fix: delete the third
      argument.

Patch Changes

  • 8abf133: Breaking (discovery response shape): retire the residual feed capability surface (#3180, follow-up to #1959 / ADR-0052 §5).

    The feed backend was retired long ago; #1959 removed the feed contracts + SDK. This
    removes the last discovery/dispatcher references to it, and fixes a real bug where the
    comments capability was permanently false.

    • @objectstack/specWellKnownCapabilitiesSchema.feed and ApiRoutesSchema.feed
      (routes.feed) are removed, and the /api/v1/feed entry is dropped from
      DEFAULT_DISPATCHER_ROUTES. FROM → TO: clients reading discovery.capabilities.feed
      or discovery.routes.feed → use discovery.capabilities.comments; comments/activity
      are served by the generic data API on sys_comment / sys_activity
      (/api/v1/data/sys_comment/…).
    • @objectstack/metadata-protocolgetDiscovery() no longer emits the always-false
      feed service/capability. Bug fix: the comments capability previously keyed off
      the deleted 'feed' service (so it was permanently false after #1955); it now tracks
      the presence of the sys_comment object (provided by the always-on audit slate), so
      declared === enforced.
    • @objectstack/client — the internal feed: '/api/v1/feed' route constant is removed
      (it only existed to satisfy the now-removed ApiRoutes.feed type; no client code used it).
  • Updated dependencies [f972574]

  • Updated dependencies [6289ec3]

  • Updated dependencies [22013aa]

  • Updated dependencies [3ad3dd5]

  • Updated dependencies [8efa395]

  • Updated dependencies [3a18b60]

  • Updated dependencies [a8aa34c]

  • Updated dependencies [e057f42]

  • Updated dependencies [a3823b2]

  • Updated dependencies [43a3efb]

  • Updated dependencies [524696a]

  • Updated dependencies [bfa3c3f]

  • Updated dependencies [5e3301d]

  • Updated dependencies [dd9f223]

  • Updated dependencies [46e876c]

  • Updated dependencies [5f05de2]

  • Updated dependencies [021ba4c]

  • Updated dependencies [158aa14]

  • Updated dependencies [62a2117]

  • Updated dependencies [d2723e2]

  • Updated dependencies [fefcd54]

  • Updated dependencies [beaf2de]

  • Updated dependencies [369eb6e]

  • Updated dependencies [06ff734]

  • Updated dependencies [b659111]

  • Updated dependencies [5754a23]

  • Updated dependencies [6c270a6]

  • Updated dependencies [290e2f0]

  • Updated dependencies [668dd17]

  • Updated dependencies [8abf133]

  • Updated dependencies [e0859b1]

  • Updated dependencies [04ecd4e]

  • Updated dependencies [4d5a892]

  • Updated dependencies [16cebeb]

  • Updated dependencies [86d30af]

  • Updated dependencies [8923843]

  • Updated dependencies [a2795f6]

  • Updated dependencies [f16b492]

  • Updated dependencies [4b6fde8]

  • Updated dependencies [2018df9]

  • Updated dependencies [fc5a3a2]

  • Updated dependencies [8ff9210]

    • @objectstack/spec@16.0.0
    • @objectstack/core@16.0.0

@objectstack/client-react@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:24
f55be04

Patch Changes

@objectstack/cli@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:25
f55be04

Minor Changes

  • 2ea08ee: Flow trigger observability — kill the four-layer silence around record-change flows that never fire (2026-07-17 third-party eval).

    A misauthored auto-launched flow (wrong objectName, missing requires: ['automation','triggers'], failing start condition) produced ZERO output at every layer: the engine's own registration/binding logs land inside the CLI's boot-quiet stdout window (which swallows debug/info/warn — only error/fatal reach stderr), and each "didn't happen" path was itself silent. Fixes:

    • Startup banner Flows: section (os serve/os dev/os start): flow count, bound-to-trigger count, registered trigger types, draft count — plus loud lines for flows declared with no automation engine enabled (requires missing), flows whose trigger type has no registered trigger, and bound record-change flows targeting an unknown object (dead binding). Printed after stdout is restored, so it is immune to the boot-quiet window.
    • Trigger-fired run failures now log at ERROR (stderr — always visible): the automation engine no longer drops the AutomationResult of a trigger-fired execution; condition-evaluation faults and node failures surface with the flow name. Condition-not-met skips stay at debug (high-frequency, intentional).
    • RecordChangeTrigger probes object existence at bind time and warns when a flow's objectName matches no registered object (exact-name matching), instead of silently arming a hook that can never fire.
    • kernel:bootstrapped binding audit in the automation plugin: warns per enabled-but-unbound triggered flow with the reason, and reports registered/bound/draft counts (AutomationEngine.getTriggerBindingAudit(), extended getFlowRuntimeStates() with status/triggerType/object).
    • os validate flow-wiring advisories (@objectstack/lint validateFlowTriggerReadiness): warns when a record-triggered flow targets an object the stack does not define, and when an auto-triggered flow's status is draft (authored or defaulted — draft flows still fire; declare active or obsolete).
    • Removed leftover boot-debug writes (registerApp/AppPlugin/StandaloneStack/AuditPlugin stderr noise) that previous debugging of this same silence had left behind.
  • 83e8f7d: feat(mcp): decouple the stdio auto-start switch from the HTTP surface + surface the MCP endpoint on os dev boot (#3167)

    The MCP HTTP surface (/api/v1/mcp) and the long-lived stdio transport used to
    share one env var: OS_MCP_SERVER_ENABLED=true turned the HTTP surface on and
    silently auto-started the stdio transport — which bridges the raw metadata service

    • data engine with no per-request principal (unscoped). An operator setting it to
      "make sure MCP is on" got an unscoped transport as a side effect.
    • @objectstack/types — new resolveMcpStdioAutoStart(). Stdio auto-start is
      now its own switch, OS_MCP_STDIO_ENABLED (default off); OS_MCP_SERVER_ENABLED
      governs only the HTTP surface. The legacy OS_MCP_SERVER_ENABLED=true trigger
      still starts stdio for one release, flagged as deprecated. =false is unchanged
      (it only ever gated HTTP).
    • @objectstack/mcpMCPServerPlugin.start() gates stdio on the new switch
      and logs a one-time deprecation warning when started via the legacy alias.
    • @objectstack/clios dev now prints the MCP endpoint, the agent-skill
      URL, and a ready-to-paste claude mcp add command on boot (gated on the HTTP
      surface being on), so the "an agent operates the app it's building" loop is
      discoverable at dev time.
    • create-objectstack — the blank scaffold README documents that the app is
      itself an MCP server (the serve side), distinct from the consume-side connector.
  • 06ff734: feat(spec)!: remove deprecated aiStudio/aiSeat capability aliases (#3308)

    BREAKING (shipped as minor per the launch-window convention). The one-cycle
    deprecation window from #3265 is over: the legacy camelCase requires spellings
    aiStudio/aiSeat are no longer canonicalized to ai-studio/ai-seat — they
    are now plain unknown tokens, rejected by defineStack like any other typo.

    • Removed exports DEPRECATED_PLATFORM_CAPABILITY_ALIASES and
      canonicalizePlatformCapability from @objectstack/spec; isKnownPlatformCapability
      no longer canonicalizes.
    • defineStack no longer rewrites aliases (the canonicalizeStackRequires pass
      is gone); the serve resolver no longer canonicalizes raw-artifact requires.

    Migration: use the canonical kebab-case tokens ai-studio / ai-seat. All
    first-party configs were migrated in #862/#863; only stacks still carrying the
    legacy spelling are affected. Cloud's objectos-runtime (pinned to an older
    framework) follows on its next .framework-sha bump.

Patch Changes

  • 6289ec3: feat(i18n): translation slot for action resultDialog copy — the one-shot secret-reveal dialogs are now localizable

    The post-success resultDialog (temporary passwords, 2FA backup codes, OAuth
    client secrets) had no slot in the translation protocol, so its title /
    description / acknowledge button / field labels always rendered the hardcoded
    English metadata literals even on fully-translated locales.

    • spec. _actions.<action> (object + object-first node) and
      globalActions.<action> gain an optional resultDialog translation node
      (ActionResultDialogTranslationSchema): title, description,
      acknowledge, and fields keyed by the literal result-field path
      (e.g. "user.email" — keys may contain dots; resolvers index the record
      directly, never split on .). New resolveActionResultDialog overlay
      resolver, wired into translateAction for API-boundary translation.
    • cli. os i18n extract emits the new resultDialog.* keys (title /
      description / acknowledge / fields.<path> for labelled fields), so
      coverage and skeleton generation see them.
    • platform-objects. en / zh-CN / ja-JP / es-ES bundles ship the
      resultDialog copy for all six shipped dialogs: sys_user.create_user,
      sys_user.set_user_password, sys_two_factor.enable_two_factor,
      sys_two_factor.regenerate_backup_codes,
      sys_oauth_application.create_oauth_application, and
      sys_oauth_application.rotate_client_secret.

    Client-side rendering lands in objectui (actionResultDialog resolver in
    @object-ui/i18n + result-dialog handlers). Purely additive — untranslated
    locales keep falling back to the metadata literals.

  • da58467: fix(cli): honor OS_DATABASE_DRIVER=memory (mingo InMemoryDriver) (#3276)

    os dev / os start / os serve advertised a memory database driver
    (--database-driver memory, OS_DATABASE_DRIVER=memory, and a memory://
    URL scheme), but serve.ts's driver dispatch had no memory branch — so it
    silently fell through to the dev SQLite :memory: default (SQLite-in-memory,
    a different engine) or, in production, registered no driver at all.

    The driver kind-resolution + construction is now extracted into
    utils/storage-driver.ts (unit-testable in isolation) with the missing
    memory branch: selecting it yields the mingo InMemoryDriver in dev AND
    production. The memory:// / mingo:// URL scheme is now recognized too,
    kept distinct from sqlite's :memory: pseudo-file. Telemetry-datasource
    provisioning behavior is unchanged.

  • fb107b8: fix(cli): tolerate the -- separator pnpm injects when forwarding script args (#3114)

    The AGENTS.md-documented backend-debug flow pnpm dev -- --fresh -p <port> failed at
    the repo root with an opaque Unexpected arguments: -p, 44637 (exit 2 + a help dump).

    pnpm appends forwarded args to a script verbatim, including the --, and each
    nested pnpm --filter hop preserves it, so the showcase's objectstack dev --seed-admin ran as objectstack dev --seed-admin -- --fresh -p 44637. oclif reads
    -- as POSIX end-of-flags, so everything after it became positional: --fresh was
    silently swallowed as the package arg and -p 44637 overflowed the arg list. Every
    flag the user asked for was dropped — the failure was opaque precisely because the
    -- looks inert.

    A preparse hook now drops -- separators before oclif parses argv, so the
    npm-style -- <flags> form and the bare form behave identically, for every command
    and both bins (run.js, run-dev.js). No os command takes passthrough args (none
    sets strict = false, none reads raw argv), so a -- carries no meaning here and is
    always a package-manager artifact.

    Note this is not fixable via oclif's '--': false parser option: that keeps
    flag-parsing on past the separator but re-appends the -- into argv, so strict
    commands fail with Unexpected argument: -- instead.

    Tradeoff: a --prefixed token can no longer be forced to parse as a positional
    value. Every os positional is a config path, a metadata / datasource / package
    name, or an id — none start with -.

  • 216c2db: fix(cli): fail loudly when turso/libSQL is selected in the open-core CLI (#3276 follow-up)

    Same "declared ≠ enforced" class as the memory fix: the CLI advertised turso
    (--database-driver turso, OS_DATABASE_DRIVER=turso, libsql:// URLs) but the
    driver dispatch had no turso branch, so it silently fell through to the SQLite
    default and ignored the requested engine.

    turso/libSQL ships in the cloud / enterprise distribution
    (@objectstack/driver-turso, composed by the cloud runtime's own kernel factory —
    open-core's standalone stack deliberately does not consume it). Rather than pull an
    EE driver into open-core, createStorageDriver now throws a typed
    UnsupportedDriverError for turso/libsql, and serve.ts surfaces it as a
    fatal, actionable boot error (naming the cloud/EE package and the open-core
    alternatives) instead of silently degrad...

Read more

@objectstack/account@16.0.0

Choose a tag to compare

@github-actions github-actions released this 21 Jul 06:24
f55be04

Patch Changes

objectstack-vscode@16.0.0-rc.1

Pre-release

Choose a tag to compare

@github-actions github-actions released this 20 Jul 09:01
bf72a35
objectstack-vscode@16.0.0-rc.1

create-objectstack@16.0.0-rc.1

Pre-release

Choose a tag to compare

@github-actions github-actions released this 20 Jul 08:58
bf72a35
create-objectstack@16.0.0-rc.1