/ docs · functional specification

The full platform
functional reference.

Every functional area of AI API Mapper documented at implementation depth so architects, security reviewers, and platform engineers can evaluate the product with real technical context.

Changelog · Changelog

Changelog

This page summarizes each platform release. Full technical detail is available in the repository.


Version 1.2.19

Added

  • Call Flow filters by call type and by what a call addressed. The grid's first column has always shown both — the badge, and the two identity lines under it — and neither could be filtered on, so finding one ESRA retrieval among a day of MCP traffic meant paging through it. Type offers exactly the badges the grid can show; Identity matches a fragment of either identity line, case-insensitively. Both narrow together with the tenant, caller, status and time filters already there. Identity searching reads the most recent matching calls rather than the whole range, and says so when it reaches that limit — an empty result you cannot tell apart from "not in the part I searched" is worse than no filter.
  • The opt-in correlation hash now covers ESRA exposures. Appending a short salted digest to each captured value — so you can tell whether two calls carried the same one without recording it, which on a retrieval tool means whether a caller was shown the same record again — shipped for MCP toolsets only, and every ESRA tool resolved to "off" with nothing an operator could do about it. It is now a per-exposure setting on the same terms: off by default, offered in Structural mode only, and salted per tenant per day so digests match within a day and never across tenants.

Fixed

  • An ESRA exposure's payload capture mode and window are now settable from the Portal. The exposure editor offered the capture switch and the byte ceiling only, while the runtime had honoured a capture mode and an end time on the ESRA path all along — reachable through the API alone. Worse, because an exposure update replaces the whole record, saving from the Portal sent neither field: an exposure set to Full with an end time lost both the next time anyone edited its name. Both now appear on the Fetch & logging tab, with the same warning an MCP toolset gives for Full capture left open-ended, and an exposure's window is held to the same bounds as a toolset's — it may not end in the past and may not exceed 30 days.

Version 1.2.18

A2A becomes an agent protocol. A2A was built as a protocol-level mirror of MCP tool calling — a caller named a tool and the platform dressed it up as an agent skill. That shape is removed, so there is one model: agents.

Breaking changes

  • A tool is no longer reachable over A2A. The tenant-wide A2A endpoint and the tenant Agent Card are gone. Tools remain fully available over MCP, exactly as before.
  • Every A2A interaction is addressed to a specific agent, at its own hostname https://{agent}-{tenant}.{agentsRoot}, over JSON-RPC, gRPC and REST alike. A gRPC method's URL is fixed by the protocol definition, so an agent addressed by URL path cannot be reached by a conforming gRPC client at all; a hostname per agent is what makes all three transports reachable at one address. One wildcard certificate and one DNS record cover every agent, and creating an agent needs no DNS change.
  • gRPC now uses the specification's own service definition, so the address and every message on the wire are the specified ones. Regenerate any gRPC client against the A2A specification's a2a.proto.
  • Callers no longer send skillId, and clarifying questions moved from a task's artifacts to status.message.
  • Composite Agent Cards are withdrawn. Merging other agents' skills under our own name, signed with our own key, asserts capabilities that belong to agents we do not control.

These are made deliberately, while A2A on this platform has no external consumers.

Added

  • Agents Monitoring (Governance → Agents Monitoring): a roll-up of every agent in the tenant with task counts by outcome and last activity, then its tasks, then a task's status timeline and webhook delivery history. Three views search across tasks — by state, by state entered, and by webhook delivery attempt — so a consistently failing endpoint is findable without already knowing which task to open. Read-only: A2A has the calling agent drive its own tasks. Gated on the Governance read role, so an auditor who may see a Call Flow step may also open the task behind it.
  • Task listing (ListTasks), the one specification method the platform did not implement. Paged by cursor rather than position, so a task created or removed mid-listing cannot be duplicated or skipped.
  • Per-task token accounting and ceilings for hosted agents. Every task keeps a running total across pauses and resumes, shown per task and rolled up per agent. An agent can be given input and output token limits; blank means the deployment default, not unbounded. A task that reaches its limit fails saying which limit it hit.
  • Editable agent and tenant short names. The agent editor shows the resulting address as you type. Changing one is confirmed, with the address before and after — everything holding the old address stops reaching the agent the moment it saves, and there is no redirect.
  • historyLength is honoured on all three transports. Absent means no history. A remote agent's transcript is fetched from that agent with your cap attached and never stored here; a hosted agent keeps no history at all, deliberately — the material would be the model's own working thread, including the raw tool responses the caller is not meant to see.
  • Webhook credentials. A caller may supply a credential with its push-notification configuration and the platform presents it on every delivery. Encrypted at rest, discarded once the task is finished and no delivery is awaiting retry, and after seven days regardless.
  • An effective tool catalog panel on a hosted agent's Skills tab: the union across all skills, which is what the agent can actually reach now that a caller no longer names one.

Changed

  • A hosted agent's turn runs on platform workers, not on your connection. A task is therefore observably in progress, can be subscribed to, and can fire a push notification. Whether your call waits is A2A's configuration.returnImmediately; the default is to wait. Authorization still happens before you get an answer.
  • A hosted agent declares how its turn ended by calling one of three control tools, rather than having it inferred from which tools it happened to call. Inference was wrong in ordinary use: an agent needing no tool parked forever, a preparatory lookup finished a task that had not started, and a corrected retry was reported as a failure over a write that succeeded.
  • A hosted agent no longer asks a caller for credentials. Its downstream access is an administrator's configuration; the caller cannot supply one, and asking invites them to put a credential in a message. A 401 or 403 now reaches the agent as an ordinary tool error and is recorded on the turn's audit entry.
  • A caller's tools are decided by who they are, not where they connected from. An agent belongs to a tenant, not to a client application; narrow it with access policies on the caller's identity.
  • "Allow direct passthrough" is now "Published" — the flag is simply whether the agent has an address. Publishing grants a route, never access.
  • Messages carry A2A's own model end to end: a role, any number of text, file or data parts, and the sender's own ids and metadata, relayed unchanged rather than summarised.
  • A remote agent's answer reaches you whole — every artifact, part, status.message, history and metadata, with only the identifiers rewritten to ours. Relayed conversations keep their place on the far side, and following a relayed task asks the agent running it.
  • Model-call counts read higher than before. Spend is now counted per model call rather than per turn; the numbers were understated, they have not gone up.
  • The Call Flow grid labels each call for what it is rather than calling everything a tool and a mapping, and hosted-agent turns get their own A2A Hosted badge showing what the model decided and what the turn cost.
  • Agents Monitoring grids group related columns into compound cells, and task ids are clickable to filter the grid you are on.

Fixed

  • A2A 1.0 conformance: flat message and artifact parts, ROLE_USER/ROLE_AGENT roles, the {"task": …} / {"message": …} response envelope, google.rpc.ErrorInfo detail on errors, omitted rather than null fields, Z-suffixed timestamps, and refusal before the stream opens when subscribing to a task that does not exist. The older shapes are still accepted on the way in.
  • A push notification is now the body the specification names, so conforming receivers stop discarding deliveries that were being sent and authenticated correctly.
  • Every webhook delivery is recorded, not only failures awaiting retry — the grid was empty on deployments whose webhooks worked.
  • A webhook registered alongside the message now works rather than being silently discarded.
  • A follow-up naming its task continues that task instead of starting a new one.
  • Token usage is recorded again — hosted agents reported zero on every screen.
  • A task's status timestamp is when the status changed, not when it was read.
  • One correlation id covers a whole agent turn, including across a resume, so Call Flow shows one trace rather than two.
  • A failed agent task says why it failed in its audit entry, rather than one generic sentence.
  • An agent's own name is no longer sent to the model — providers disagree about what an author field may contain, and a space in the name could make an agent unusable.
  • A hosted agent's answer is no longer stored twice in its artifact.
  • The Portal shows an agent's real address, composed server-side, and says so plainly when an agent has no address rather than showing one with a hole in it.
  • A policy constraining a skill on a remote agent is flagged as unenforceable — it can never match, and a Deny row that never matches is a restriction an administrator wrongly believes is in place.
  • Status badges on the task detail page are readable again, using the same contrast-checked themes as every other screen.
  • A2A REST responses no longer carry empty fields that were never set.

Deployment

  • Set A2a:PushNotifications:Credentials:EncryptionKey to a base64 32-byte key, shared by every service. Without it a webhook is still registered and called, but unauthenticated, and a warning says so. It is not generated automatically on purpose: a per-instance key would authenticate first attempts and fail every retry.
  • A cleartext listener must now be declared. Outside Development the platform refuses to start with a plaintext endpoint unless the deployment states that a trusted proxy terminates TLS in front of it. Terminating at an ingress remains supported — one setting says so. The gateway runs this check too.
  • A waiting A2A call holds its connection for as long as the agent takes, up to the turn budget (five minutes by default). Raise the idle timeout on any proxy in front of the platform, or ask for returnImmediately: true and follow the task.
  • Three hosted-agent limits under Runtime:A2a:HostedAgents: concurrent turns (4), queued turns (128), and turn duration (five minutes).
  • A tenant's Public agent subdomain field and a client application's public subdomain default are gone; existing values are left in place rather than cleared.

Client SDKs

  • The OpenAI, LangChain and Spring AI adapters are now 1.2.0. All three changed after their 1.0.0 was published — a major dependency line in each, and a behavioural fix in the OpenAI adapter — but kept the version of the release they no longer matched. The Maven parent moves with them, since it carries the Jackson version those artifacts resolve.
  • The Spring AI adapter now depends on client 1.2.0, not the 1.1.0 it had been pinned to, so it carries the session-recovery fix rather than resolving a client that predates it.
  • The .NET adapters are 1.2.0 as well — Semantic Kernel, Microsoft.Extensions.AI, and Azure AI Foundry at 1.2.0-beta.1, which stays prerelease because the Azure agents library it wraps is. Their own code is unchanged; the version moves because each now depends on client 1.2.0, and the same package version must not describe two different dependency graphs.
  • The OpenAI and LangChain adapters now declare the versions they are actually built againstopenai >= 7.0.0 and @langchain/core >= 1.0.0, rather than the 4.x and 0.2 floors that predate the dependency upgrades and that nothing verifies.

Version 1.2.17

A correctness release for A2A agent discovery. The Agent Card this platform publishes did not match the A2A 1.0 specification in several places. Nothing about who may see or call a skill changes; what changes is the JSON an A2A client reads when it discovers one of your agents.

Breaking changes

  • The authentication requirement list is securityRequirements, not OpenAPI's security, and both it and the schemes it refers to use A2A's structure rather than OpenAPI's. A scheme's kind is now the name of the property carrying it, not a type field. A client written against the published A2A specification, or a standard A2A library, works with the corrected card and did not work with the previous one.

Added

  • Discovery is two steps, as the specification intends. The anonymous card answers what can this agent do — identity, address, how to authenticate, and every skill the tenant has published. An authenticated client then asks for the extended card and gets what may I do: the same card narrowed to the skills its own identity may invoke. It used to list no skills at all when fetched anonymously, which made an agent look broken. The public card is a description, not a permission: every call is still authorised exactly as before.
  • Skills have a published id, tags and examples. The id is derived from the name (spaces and underscores to dashes, lower-cased), so "Company Documents Search" publishes as company-documents-search; the editor shows the id a name will produce as you type. Tags are what agent registries and routing clients filter on. Existing skills get ids on upgrade; two names differing only in spacing or case produce one id, and the second gets a numeric suffix you can rename away.
  • Hosted and registered agents can have their skills discovered at all. Their card was anonymous and their endpoint accepted only message sends, so their skill list came back empty regardless of who asked.

Fixed

  • A bearer scheme says that it is a bearer scheme. The card declared it wanted a token but not what kind. A test now reads the published JSON back rather than the platform's internal object.
  • Both authentication methods are declared. The Runtime accepts a bearer token or an API key, but the card named only the token — telling a client holding a valid API key it could not call the agent.
  • Signed cards can be verified by someone other than us. The platform signed a form of the card no other A2A implementation would arrive at: non-Latin text was escaped before signing, numbers were signed as written rather than in one agreed form, and empty fields were not dropped as both signer and reader are required to do. Tests now check the exact bytes.
  • A signed card says where to find the key that signed it, and declares its signature type. Reading another system's card, the platform follows that address for its path only — the host stays the one the card came from, so a card cannot send us anywhere it could not already.
  • A public agent card fetched through the front door is no longer refused by the ingress, which demanded a credential for a card the platform serves to anyone.
  • Endpoint URLs are handed over ready to use — no {clientId} placeholder for the recipient to finish. Both the invocation URL and the Agent Card URL are shown complete, each with its own Copy button, in the Agent Directory row action and the agent's Details tab.
  • Fields with no value are left out rather than sent as empty, including an unsigned card's signature list. An unsigned card means the tenant has no signing key yet — keys are created by the background jobs worker, so if yours is not running, cards stay unsigned.

Version 1.2.16

A security release. The platform's own security scan was run end to end for the first time against a published build, and everything it found at critical or high is closed. Nothing here changes how the platform behaves for an existing tool, mapping or credential.

Fixed

  • Every known vulnerability in a shipped dependency is closed — 72 advisories across four vulnerability databases, now at zero at every severity. Most were in the Java SDK's JSON library and in the build tooling of the two JavaScript trees; none was in a component that serves a request.
  • Container images are current again. Every image is pinned to an exact patch release rather than a moving tag. The previous images shipped a .NET runtime six security patches behind without anything saying so, and the admin portal's web server carried a further seven critical and eleven high findings from its own base. It is also 40% smaller. The pin is now reviewed against upstream at every release.
  • An open redirect in the admin portal. The portal's plain-http:// redirect was built from the address the caller claimed to be visiting, so a crafted request could be answered with a redirect elsewhere carrying the portal's own name. It now redirects only to the hostname the deployment declares.

Added

  • A printable security posture report alongside the raw tool output: verdict, severity counts, every layer and what it found, and the exact image tag, registry and commit examined. It collapses duplicate findings to the number that matters — the same vulnerable package reported by three tools is one package. A scan whose live-attack stage could not start is reported as an unfinished report rather than a clean one, and a finding judged not to be a defect is recorded as such in the code with its reasoning.
  • A layer that scans the platform's own AI tool descriptions for poisoning. ApiMapper writes those descriptions with an LLM from the specification you import, which is a supply chain: a hostile specification could try to smuggle instructions into a description every connected AI client later reads as guidance. It runs entirely on your own infrastructure — no tool name or description leaves the machine — and is reported without blocking a release, because pattern matching is noisy by nature.

One deployment setting. Set PORTAL_PUBLIC_HOST on the portal web container to the hostname your portal is reached at — apimapper.example.com, no scheme and no port. Leave it unset and plain http:// requests are refused rather than redirected; HTTPS is unaffected either way. CONFIG_REFERENCE.md has the detail.

Read the TLS layer carefully. A self-hosted run inspects a certificate the scan itself generated, so certificate findings are counted and named but not gated in that mode. Pointed at a real deployment with --target, they gate like everything else. A self-hosted run is not a verdict on your certificate.


Version 1.2.15

A correctness release for field mappings.

Fixed

  • Two fields can no longer be published under the same name. A mapping could expose two different response properties under one name and publish without complaint — after which the tool schema described one field while the value returned came from the other, so a model could be told a field was a whole number and handed text. Saving in that state is now refused, naming both fields and the response each sits under. The rule is about the full published path, so a customer's name and a vendor's name can both be published as full_name: they sit in different objects. One field appearing under several response codes is normal and left alone.
  • OData and Microsoft Graph field selection goes out in the right syntax. $select-style parameter values were joined with dots, which neither service expects — standard OData separates a property path with a slash, and Microsoft Graph must be asked for a whole top-level property. Any selection reaching below the top level of an object was rejected by the service. The platform now writes each name in the form the endpoint's own service accepts, decided from what was recorded at import. Nothing to configure, and what the AI client is told to write no longer depends on the service, so repointing a mapping between OData services does not reshape its tools.
  • A selectable field is offered under a name the target service accepts. The list of values an AI client could ask for named the field's position in the response rather than anything the service understands — against Microsoft Graph it offered emailAddress, which is not a property of a message, while sender appeared nowhere. Two fields inside the same Graph property are now a single choice. AI clients see the corrected list the next time they read the tool definitions.
  • Edits made while creating a new version are saved. The "Create mapping version" dialog showed the full field editor but sent only the change summary, so every rename and inclusion change was discarded and the new version silently carried the previous version's names. This matters most for a published mapping, where creating a version is the only route to an editable copy. The enrichment checkbox now behaves as it reads, too: a field unselected before saving stays excluded through the run.
  • Fields whose own name contains a dot are published where they belong. @odata.nextLink and @odata.count were read as a field inside an invented @odata object, so both landed in the wrong place in a tool's response schema and collapsed onto each other. Corrected for existing mappings as well as new ones — the next time such a mapping is published, its schema simply becomes right.
  • Rejected requests say what was wrong. Every refused save showed "One or more validation errors occurred." and nothing else; the specific reason was in the response but never displayed. This affects every screen in the portal.
  • Semantic enrichment no longer loses a whole run to duplicate field names. A model asked to name the fields of one payload will sometimes give two of them the same name, which produced a mapping the platform would not store — so the entire proposal was discarded after the model had been paid for it, and the run was recorded as a cancellation. Enrichment now keeps one proposed name, derives the other from the API's own field, and lists every such change in the run's warnings. A proposal refused for another reason is reported as refused, with the reason.

Upgrade note. Existing mappings keep working exactly as they are, including any containing a duplicate name: nothing is taken offline and no republish is needed. Such a mapping refuses to save the next time it is edited, naming the two fields and the response each sits under; rename one — in the create-version dialog if the mapping is published — and it clears.


Version 1.2.14

A small accessibility release. It completes the third of the three items reported in 1.2.13 — the one described there as a change we were making deliberately over time rather than partially.

Form labels throughout the portal are now attached to the fields they name. Previously most were not, which meant assistive technology announced those fields without their label, and clicking a label did not put the cursor in its field. Both now work, on every form in the product. Where a heading names a group of controls rather than a single one — a list of allowed issuers, a set of tools, a row of switches — it is now announced as the name of that group.

Nothing moves on screen and nothing behaves differently for anyone using a mouse. There is no change to how the platform behaves at runtime and no upgrade step.

Three further fixes landed in this release, all in the administration portal.

  • Deleting an ESRA exposure works. The Delete action on the Exposures screen answered "not found" and left the exposure in place. Anyone who hit this can now delete as intended; nothing was ever partially deleted by it.
  • Tool oversight no longer loads every tool at once. The Security area's tool list fetched the whole registry on every visit, which grows with each published tool. It now loads a page at a time, with a record count and a per-page control, and the search and filters above it continue to narrow the whole registry rather than the page on screen.
  • The workflow definition field on a target system's auth profile now appears only where it applies. It was offered for every authentication strategy with "None" as its default, which allowed two mistakes: a profile carrying a workflow that would never run, and a workflow-based profile carrying no workflow at all — the second saved cleanly and then failed when a tool was called. The field is now shown, and required, only for the workflow-based strategy, and the platform refuses a workflow-based profile that does not name a workflow it can execute. Existing profiles are unaffected.

The only API change is one added endpoint behind the tool oversight screen; nothing existing changed shape, and there is no database migration.


Version 1.2.13

A maintenance release, and the companion to 1.2.12. That release went through the server side of the platform looking for parts no automated test had ever exercised. This one does the same for the administration portal you are reading this in.

Around 960 new tests now cover screens that had none: the editors where toolsets, mappings and audit targets are configured, the retrieval-source wizard, the identity-provider screens, and — first of all — the rule that decides which controls each person is allowed to see and use. That rule is applied on every screen in the product and had never been tested directly.

Three issues were found. Two are fixed; the third is a change we are making deliberately over time. None had been reported, and none needs anything from you.

  • The sign-in screen's "Tenant" option now works. If your organisation is not listed among the sign-in options offered, there is a Tenant option for entering your tenant ID and finding your provider that way. It was not responding when clicked. It is the only route to sign in for people in that position, and it now opens as intended.
  • The audit target form no longer closes while you are typing an address. In one particular configuration, editing the endpoint address of an external audit destination could close the form and lose what you had entered. The form now keeps its place, and the preview it shows beside the address simply waits until the address is complete.
  • Improving how form labels are read by screen readers. Most labels in the portal are not formally attached to the field they name, which means assistive technology does not announce them and clicking a label does not put the cursor in its field. This affects most forms in the product, so we are correcting it as its own piece of work rather than partially. Nothing behaves differently for anyone using a mouse.

There is no change to how the platform behaves at runtime, no change to any API, and no upgrade step.


Version 1.2.12

A maintenance release. No new capability — this one is about making sure the platform keeps doing what it already does. We went through the codebase looking for parts that had never been exercised by an automated test, wrote those tests, and fixed what they turned up.

Roughly eight hundred new tests now cover things that had none: how a downstream response is read and reassembled before an AI client sees it, the rules that check every administrative form you submit, the retry and health behaviour behind audit delivery, and the background jobs that run without anyone watching.

Five issues were found and fixed, across four areas. None had been reported, and none requires any action on your side:

  • Addresses configured for outbound calls are checked more strictly. Several places accepted a value that looked like a web address without confirming it was actually reachable over HTTP — so a mistyped address could be saved and only fail later, when something tried to use it. It is now rejected at the point you enter it.
  • "Already exists" now means it already exists. When adding an external directory to a sign-in provider's allow list, any failure at all was reported as a duplicate. If the save had genuinely failed, you were told the entry was there when it was not. The same applied to assigning a provider to a tenant.
  • Tenant separation in the runtime cache is enforced more robustly. An internal identifier could, with unusual configuration values, have been ambiguous. It is now unambiguous by construction. Deployments rebuild their cache once on upgrade — no action needed, and there is no change to what anyone can see.
  • A clearer error when a delegated token is not what the platform expects. Checking such a token could fail in a way that produced a generic error instead of the explanation it was written to give you.

We also added a guard against this happening again. The build now fails if a new component is added without any test naming it. Deliberately a floor rather than a coverage target: the point is to notice code nobody has exercised at all, not to chase a percentage.


Version 1.2.11

An AI can now ask for fields by the names you gave them. Some APIs let a caller name which fields to return — Microsoft Graph's $select is the familiar example. But the names those APIs expect are their own, and the whole point of a mapping is that you rename them into something an AI can understand. The AI asked for title and startDate; the API wanted subject and start, and refused the call.

An input parameter can now be marked as a reference parameter, meaning its value names response fields rather than carrying data. You pick which fields it is allowed to name, and the platform translates them back to the source names on the way out. The AI works entirely in your vocabulary and never learns the API's.

You decide which fields can be reached this way. A reference parameter is a list you curate, not an open door: a field you did not select cannot be requested through it, and a name the AI invents is dropped rather than passed on to your API.

Changes in this release:

  • A new Type column on request parameters — Normal, or Reference with a searchable picker over the endpoint's response fields
  • A live preview showing exactly what will be sent (title → subject), so a configuration can be checked rather than trusted
  • Excluding a response field withdraws it from every parameter that names it — and puts it back if you change your mind before saving
  • OData and Microsoft Graph imports arrive pre-configured$select comes ready to edit rather than waiting to be set up on every operation
  • Nothing in the platform is specific to Microsoft Graph or OData — the same setting serves any API whose parameters name its own fields, and an import only ever suggests: your configuration is never overwritten
  • Fixed: saving a mapping quietly discarded where each parameter belonged (query string, path, header), which could reshape a request that had been working

Version 1.2.10

An agent conversation is no longer kept once the task it belonged to is finished. An A2A task that pauses to ask a question keeps the conversation behind it so the task can be resumed when the caller answers. Once the task is finished there is nothing left to resume — but cancelling a paused task kept its conversation anyway, indefinitely. A finished task now releases it, whichever way it finished.

A task nobody ever answers is now closed out. An A2A task can legitimately wait days on a person, and nothing told one still waiting apart from one that had been abandoned. A task that goes 30 days without an update is now marked failed, which releases the conversation it was holding. It is closed rather than deleted: a client that comes back late gets a proper finished task rather than an error it cannot interpret, and the closure is visible in the task's own history.

Finished tasks now age out. A task's output — what an agent produced and returned to the caller — is your content, and it now has a retention clock like every other kind of record on the platform. A task that has been finished for 30 days is removed along with its status history, on the same nightly cleanup that already ages out audit records and expired sessions. Both windows are configurable per deployment.

Changes in this release:

  • A finished task releases its conversation — enforced when the task is written, not left to each code path to remember
  • Abandoned tasks are closed, never deleted — a late client always gets a well-formed answer
  • Two windows, not one — the conversation is needed only while a task is live, its output only once the task is finished, so the two are governed separately
  • No new background job, no new table and no database change — the existing nightly cleanup does the work

Version 1.2.9

Audit logs now record the shape of a payload instead of its contents. The platform can log the requests and responses flowing through it, which is invaluable when a tool misbehaves — but the data belongs to your downstream API, and we cannot know which fields carry a patient name, a bank account or a salary. Payload capture is now built so that chasing a bug does not mean keeping customer data.

Payload capture now has two modes. Structural, the new default, records each field's name, type and size but never its value. You can still see that the client sent a customerId, that the response came back with five thousand orders, that a field was populated rather than empty, and that the downstream added a new field last week — without any customer data being written down. Full keeps the previous behaviour for when you genuinely need the values.

If you have payload logging switched on today, those toolsets move to Structural when you upgrade. Set them back to Full if you need values captured.

Payload capture can now be given an end time. Logging turned on to investigate an incident stops on its own instead of being left on indefinitely, and the Portal flags Full capture left on with no end time.

Identifiers in the URL are reduced too. Redaction now covers the whole request line: values in the path and the query string are reduced the same way the body is, rather than the query string alone.

Changes in this release:

  • Structural capture by default — field names, types and sizes; no values, and no keys from data-keyed lists
  • A capture window — payload logging expires on its own, per toolset or per endpoint
  • Payloads age out separately from the records — bodies are kept for 30 days by default, the audit record itself for a year, and an aged-out body is marked rather than silently missing
  • Reading a captured payload is itself audited — the event records who looked and at which record, never the contents
  • Optional correlation hashes — tell whether two calls carried the same value without recording it; off by default
  • Catalog operations still log in full — listing the available tools, resources or prompts, and fetching a tool's schema, record the actual listing. That content is your own published tool configuration, which every connected client already receives in full, and summarising it would leave you with "47 tools were listed" instead of which ones

Version 1.2.8

Saving a toolset is one operation again. A toolset save used to be a sequence of writes — the toolset, each endpoint's downstream credentials, each endpoint's access policy, then the toolset again to publish it. Twenty endpoints meant more than forty writes for one click of Save, with two consequences this release removes.

  • Connected AI clients are no longer flooded when you save. Every write told the Runtime its catalog had changed, and every client answered every notification with a full tools/list — a burst of dozens of requests within seconds, enough on a busy tenant to hit the rate limit and leave clients briefly refused. A save now announces itself once, whatever it changed.
  • A save that fails no longer leaves half the endpoints configured. Everything a toolset save touches is written in a single transaction. Previously a failure part way through left some endpoints bound and others not, and only a newly created toolset was cleaned up.

Changed

  • Publishing no longer needs two saves. A toolset can be created directly as Published; it previously had to be written as Disabled first, because publishing checks credentials that had not been written yet.
  • Deselecting an endpoint removes its credentials and its access policy, rather than leaving a binding attached to a tool the toolset no longer publishes.
  • Changing a toolset's tool detail level is a single change again — switching between Full, Data Structure Only and Lazy rewrites every tool, and used to announce each one separately.
  • Lazy is no longer the more expensive detail level. It was trimming only the request side, so the full response contract went out for every tool — on an API whose responses are larger than its requests, that made Lazy cost more than Data Structure Only. Lazy now holds back the response contract too, still a single schema-discovery call away. Connected clients are unaffected.
  • Cached identity-provider metadata is released after a day without use, so a platform with many tenants keeps a bounded cache.

Fixed

  • The exposure mode was silently reverted on save. Changing whether a toolset is reachable by external MCP clients, by Hosted Agent Skills, or both, was discarded with no indication.
  • Adding an endpoint to an existing toolset did not always register its tool, leaving it selected in the editor but its security settings unwritable.
  • Two list tools described a response field that had no name, so an AI client had nothing to match against and could not read the list at all. Such a response is now always described under result.
  • Delegated calls to a downstream system. On-Behalf-Of and the other delegated grants now resolve the caller's identity correctly, so those calls succeed and the audit record carries the user behind them.
  • A trusted issuer naming its user claim differently now works. The Runtime honored the setting when recording who called but not when deciding whether there was a user, so delegated access stayed refused however the provider was configured.
  • Editing a trusted issuer takes effect on the next call rather than waiting for a restart, and key rotation is picked up on the provider's own schedule.
  • An access policy naming an issuer that is no longer trusted can be repaired. The picker showed one issuer selected but offered nothing to remove, so the only route was clearing every issuer and starting again — and saving without removing it failed, reported as a server error rather than a validation message. The stale issuer is now listed, marked No longer trusted and ticked, so it can be removed on its own. It is shown rather than dropped on purpose: discarding it silently would change who the policy admits without anyone seeing it.
  • Imported Microsoft Graph operations could not filter, sort, or page. An operation reached by navigating from the signed-in user — nearly every Graph operation — was generated with only its path parameters, because Graph's metadata does not state which collection a navigation property leads to and the importer read that silence as "supports nothing". Such an import now generates $filter, $select, $expand, $orderby, $top, $skip, $count and $skiptoken. Generic OData imports are deliberately unchanged: a service that does not describe its own capabilities should not have them assumed. Re-import the API and re-publish the mapping to pick up the new parameters.
  • Public Site and documentation copy is consistent again — one spelling convention and straight punctuation throughout, and the homepage protocol strip names MCP and A2A rather than mixing an identity protocol into a list of ingest formats. Error-code identifiers keep their spelling, and no license wording changed.

Version 1.2.7

A toolset is now the thing you manage, and mappings are added to it. An MCP toolset is what an AI client connects to, but it could only be created from inside a single mapping and was permanently tied to it — exposing endpoints from two APIs through one connection meant two toolsets and two client configurations. A toolset now draws its tools from as many mappings as you like, and Tools Management opens on the toolset.

Existing toolsets are migrated automatically as part of the standard database upgrade. Every toolset keeps its mapping, every tool keeps its identity, and no access policy, credential binding or client configuration has to be touched.

Changed

  • Create a toolset, then add mappings to it. Each added mapping gets its own card for its target system, authentication profile, default access policy, and which endpoints become tools.
  • Downstream settings moved to where the decision is — per mapping rather than per toolset, because a toolset spanning two APIs reaches two different systems. A toolset with one mapping behaves as before.
  • A toolset belongs to one tenant, and you choose it first. A toolset is reached through one tenant's runtime URL and governed by that tenant's policies, so one mixing tenants was never servable.
  • Two views of the same data, with a remembered toggle. MCP Toolsets lists one row per toolset with the mappings it draws from; Mappings keeps the card-per-mapping view. A toolset spanning several mappings appears under each, with a count, so it is clear before editing that a change reaches further than the card you opened it from.
  • Client applications and mappings are added and removed from a search box, not picked from a wall of cards, and any mapping can be removed including a toolset's last. Including an endpoint no longer unfolds its settings — an expand icon does — so a toolset exposing thirty endpoints stays readable.
  • Every warning a toolset carries is visible without editing it, including in the read-only View details a user without publish rights can open.
  • Adding a mapping never disturbs the tools already in the toolset — tool identity does not include the mapping, so policies, credential bindings and audit history stay where they were. A deprecated mapping removes only its own tools.

Added

  • Two mappings cannot publish the same tool name into one toolset. MCP tool names are {toolset}-{endpoint} and a call resolves by that name, so a collision would mean one tool silently answering the other's calls. Refused on save, naming both mappings. Nothing is renamed automatically — that would move a tool underneath clients already calling it.
  • A duplicate that slips in anyway is flagged, not hidden. Republishing a mapping can rename an endpoint onto a name another mapping in the toolset already uses, and that republish is deliberately not blocked — failing a mapping publish over an unrelated toolset's shape would be worse. The toolset is marked wherever it is listed, the editor badges each colliding endpoint, and Security sees it on Tool Oversight. Both tools stay callable until you resolve it; deselecting either clears it.

Version 1.2.5

A rebuilt authorization model: roles are permission bundles, and scope belongs to the grant. A role is a named set of permissions written as area:level, and a user's authority is the union of the roles they hold. Levels form a ladder inside a single area and carry nothing across areas. Scope has moved off the role's name and onto the grant: the same Security → Manage role administers one tenant when granted against that tenant, and every tenant when granted against none. The fifteen separate GLOBAL_* roles are gone, and with them the class of mistake where a role and its global twin drifted apart.

Existing grants are migrated automatically as part of the standard database upgrade. No role has to be re-granted, and no user's effective authority changes.

Changed — authorization

  • An area role is usable on its own. Every admin screen needs to name things another area owns, and obtaining a name used to cost the full administration role for that area. A lookup tier now returns identity only — an id and a name, never configuration, never a value — and each area role carries exactly the lookups its own screens need. Six screens that returned an authorization error inside a picker now work.
  • Every screen and gated control declares the permission it needs in one place, checked automatically against what the endpoints behind it actually require, so a screen cannot be visible under one rule and reachable under another. Four screens whose declared and enforced authority disagreed are corrected.
  • One gating rule across the Portal: no read and the control is not shown; read but not write and it is shown disabled, with the missing role named; write and it is enabled. Hiding a control from someone who can see the thing it acts on tells them the platform cannot do it, rather than what to ask for.
  • The dashboard adapts to the areas you hold, and notifications reach whoever administers the thing they are about rather than being a tenant-administration privilege.
  • You can only grant roles you hold yourself. Roles of areas you do not hold appear greyed out with a note saying why. Editing a user who holds roles you cannot grant still works: those grants pass through untouched, and you may remove them.

Changed — tool ownership

  • A tool's security rules belong to whoever publishes the tool. Access policies and endpoint authentication bindings were filed under Security even though a toolset or ESRA exposure creates and destroys them, and ownership was determined by parsing the tool's identifier as text. Every tool is now a registered identity with a real reference, and its rules hang off that — so a publisher sets them from the screen that publishes them, using its own area's authority, and only ever sees its own tools.
  • New Security → Tool Oversight screen. It reads every tool in scope whoever publishes it, and offers exactly two actions: take a tool offline, and clear a leftover row whose publisher no longer exists. It authors nothing. Taking a tool offline is immediate and cannot be undone by its owner — the Runtime refuses every call whatever the tool's own policies permit, and the reason is shown to the owner and audited.
  • Visible change: the tools screen shows no tools for a mapping whose newest version is deprecated, matching what the Runtime actually serves. The two previously disagreed.
  • The database upgrade is one command again. Data backfills run as part of apply, and status reports outstanding backfill work alongside outstanding schema work.
  • Four scopes — see which tools exist, call them, see which agents exist, message them — deliberately few enough to reason about at a consent screen. Discovery and invocation are each gated on their own scope, checked before any per-tool policy runs, so consent is a ceiling rather than a policy dimension an operator can forget.
  • The scopes granted are the intersection of what the user approved and what the client registered, never the union, and the approval is recorded when given — so re-registering a client cannot widen it.
  • A client can manage its own registration through the standard protocol endpoints, using a credential issued once at registration. It cannot reach any other client's registration, and the platform answers identically whether a client is unknown or the credential is wrong. A client may only use the grant types it registered for, and registrations that never complete a sign-in are swept away.
  • Fixed: a client using http://localhost for its callback, or binding a different local port each run, was refused. Both are what native and MCP clients conventionally do.

Changed — hardening and operational correctness

  • Portal access tokens are signed with a private key the Portal alone holds, validated elsewhere against the matching public key at a standard JWKS endpoint. A second, retiring key can be configured during a rotation, so a key can be replaced without invalidating sessions in flight.
  • A resilience policy — retries, per-attempt timeouts and a circuit breaker — applies to every outbound call the platform makes on a tenant's behalf. Retries are deliberately not applied to unsafe HTTP methods: the platform cannot know whether a downstream write that timed out was applied.
  • The MCP surface has a working kill switch (Runtime:Transport:ExposeMcp) and a configurable request body ceiling (Runtime:Transport:MaxRequestBodyBytes, 1 MB by default).
  • The admin Portal is served with a full browser security policy, derived per deployment from the configured gateway origin. Password hashing raised to the current OWASP work factor, upgraded transparently at next sign-in. Session revocation survives a restart and reaches a newly scaled-out instance.
  • Secrets are bound by identity rather than by label, so renaming one does not silently repoint the configuration that used it, and a removed secret fails loudly instead of falling back. A secret resolves inside the tenant that owns it; asking for a name your tenant does not hold is indistinguishable from asking for one that does not exist.
  • Adding a private or loopback address to the outbound allowlist requires platform scope, and can be turned off deployment-wide. Every write is checked against the area that owns the data, and an authorization refusal returns a clear "forbidden" rather than an unexpected error. Behavior change: creating or rotating an inline LLM credential is a Security operation — the AI Settings form shows the inline option disabled with the reason.
  • Fixed: the "Run enrichment" switch was silently off when creating a new mapping version, for every tenant with model profiles configured. Fixed: the Agent Card's signature can now be verified over its path-based URL.
  • Supply-chain and deployment hardening across the release pipeline: mandatory image signing, a reduced production container surface, locked dependency versions, and a build that fails on a production dependency advisory.

Upgrade note. A production deployment must now supply an RSA signing key pair for Portal tokens (Authentication:SigningKeyPem). Portal API refuses to start in Production without it, unless Authentication:RequireAsymmetricSigningInProduction is explicitly set to false as a temporary migration measure. See the Configuration Reference for generation and rotation.


Version 1.2.2

A2A Hosted Agent mode — LLM-backed agent skills. A registered agent can be a Hosted Agent instead of a proxy to a remote peer: an LLM-backed reasoning agent that runs admin-defined Skills over a curated subset of your Mapping tools. It recognizes an incomplete request and asks a clarifying question instead of failing outright, then resumes the same conversation on the caller's follow-up. Every tool it calls goes through the platform's existing authorization, credential brokering and audit pipeline unchanged — the LLM never gets a bypass path to a downstream API.

  • A skill is a name, a prompt, and an explicit subset of individual tools drawn from the tenant's MCP toolsets and ESRA exposures — never the whole catalog, and never a whole Mapping when only some of its tools should be agent-reachable.
  • MCP toolsets and ESRA exposures can be marked "Hosted Agents only" or "MCP clients + Hosted Agents" alongside the existing "MCP clients only".
  • Structural prompt-injection defense: a turn can only ever see and call the tools explicitly assigned to it, and the caller's message can never rewrite the admin-authored system prompt.
  • Every turn is audited with its actual decision content — the tool it chose, the question it asked, its token spend — not just success or failure.
  • LLM connectivity reuses the platform's existing connection management, the same one semantic enrichment already uses.
  • New functional documentation: A2A Hosted Agent Mode

ESRA — the Enterprise Semantic Retrieval Agent. An AI client can ask a question in plain language and receive governed evidence from your own enterprise databases, published as an ordinary MCP tool through the existing Runtime. There is no vector database, no embedding pipeline, and no copy of your data unless you ask for one: retrieval runs on the native full-text search engine of the database itself. Because it is an ordinary tool, everything that already governs a tool call governs a retrieval call unchanged.

The design principle throughout is that the AI model proposes and the platform's deterministic logic decides. A service model chooses among the sources a caller is already authorized to reach — seeing business descriptions only, never a schema, a host, or a credential — and proposes search strategies; it never writes or sees SQL. Every plan is validated before it can run. If the model is slow or unavailable, retrieval still works: every model-assisted stage has a deterministic fallback, and the response is marked degraded rather than failing.

Configuration and governance

  • Three levels — sources, capabilities, exposures — with a narrowing-only invariant: an exposure may lower a limit, remove a source or drop a response mode, never the reverse. A widening override is a publication error with a named reason, never a silent clamp.
  • Each exposure has its own access policy under the platform's existing governance model, so one capability can be published to two audiences over different source subsets. ESRA tools compose additively into the existing catalog: a tenant with no ESRA configuration sees exactly the catalog it saw before.
  • A new ESRA & Data role area, whose two management roles are independent — so publishing enterprise data to an AI client requires sign-off from distinct role holders in sequence.
  • A source actively serving traffic cannot be edited in place. Changes require an explicit unpublish, which is itself blocked while a published exposure depends on the source; disabling removes it from live traffic immediately, which is what allows a correction when unpublishing is blocked.
  • An exposure's published tool name must be unique across the tenant's entire tool catalog, not just among other ESRA exposures.

Safety

  • Every query is built from validated configuration rather than untrusted input, with row limits and ordering applied server-side, inside a read-only transaction with a statement timeout.
  • Record-level access filters derived from the caller's claims are applied as part of every query and fail closed: a caller lacking a required claim skips that source entirely rather than querying it unfiltered.
  • The retrieval model's tasks are isolated from caller and document content, and its output validated against an allow-list — an identifier it was never given is dropped and logged, and a fabricated citation invalidates the whole answer.
  • Document fetch uses encrypted, expiring references bound to tenant and exposure, re-authorized on every fetch because a reference is a pointer and never a grant, and bounded by a distributed hourly character quota — the control that stops fetch becoming a corpus-download API.
  • An exposure can optionally warn the calling AI application about prompt-injection risk in retrieved content, through two independent, off-by-default settings. ESRA's own model is always protected regardless; both settings exist to warn the calling application, which ESRA does not control.

Source engines. PostgreSQL, SQL Server, MySQL/MariaDB, Elasticsearch/OpenSearch, MongoDB and Oracle, each using that engine's own native full-text search. Search values are always passed as values, never as query syntax — verified against adversarial input per engine, including MongoDB's operator-shaped terms and the boolean-mode metacharacters of MySQL. Where an engine fails outright without a full-text index rather than merely running slower, that is reported as unusable rather than degraded. Oracle Text is separately licensed, and the health probe distinguishes "not licensed" from "cannot check" rather than collapsing them.

Internal document store. Administrators upload .txt, .md, .csv, .pdf and .docx files that become searchable content in their own right, segmented per format so ranking is not diluted by document length. Upload protections guard against disguised file types, compressed-file bombs and XML-based exploits; content flagged for possible prompt injection is quarantined for operator review rather than silently indexed or bluntly refused. A review screen shows every processing state and a quarantine queue showing what the scanner matched.

Operating it

  • Guided source onboarding: a wizard reads the database's own catalog — relations, columns, keys, full-text indexes — and proposes the mapping. It never guesses which columns are filterable or restricted: those are governance decisions, and a security control set by heuristic is worse than one left unset.
  • Try a query runs the real pipeline against a published exposure and shows every stage. It writes one operator-action audit record and no invocation records — an administrator testing a query must never appear in the trail as a caller having retrieved data.
  • The Call Flow trace explains a retrieval call end to end: every stage named, iconed and timed, including each individual source query; the caller's prompt and the response they received after masking; which sources were considered, selected and passed over; and the search terms as planned intent. The underlying database query text is never recorded, and neither is an entity's underlying table name.
  • Scheduled health probes drop a source whose database went away out of retrieval scope on its own, and a partially healthy source names the specific entity — and column, where the engine can tell — at fault. Index and schema advisories are surfaced separately and never block a source.
  • Token usage is reported per capability and across the platform, input and output separately since output is priced higher. Failed and retried calls are counted; an estimated figure is labeled as one. Tracking runs off the request path, so it adds no latency.
  • Circuit breakers replace per-query retries: a struggling source fails fast for concurrent queries rather than each retrying independently. An opt-in, access-scoped result cache can collapse a burst of near-identical queries, scoped so two callers whose permissions narrow a source differently can never share a result, with masking always re-applied on read.
  • Planning across sources runs concurrently, per-source latency is tracked with tenant-level detail, and driver connection pools are pre-warmed at startup.

Grounded answers compose from retrieved evidence and never fail an invocation — retrieval has already done its work, so a failure returns the evidence with a warning rather than discarding a usable result set. The two answer-generating response modes are publishable, subject to a per-source opt-in a capability alone cannot override, and the Portal shows each mode's cost implication up front rather than leaving it to be discovered on the usage screen.

ESRA is included on every plan at no additional cost.

Also in this release

  • Listing mappings is substantially faster on tenants with many mapping versions — the list loads only the summary information it displays. Response fields, ordering, filtering, counts and pagination are unchanged.
  • Database migrations are verified against both supported engines as part of the release process, closing several PostgreSQL-specific issues that had gone undetected.
  • Semantic enrichment progress updates are throttled to at most every few seconds or on meaningful milestones, rather than published per field, without changing what the Portal shows.
  • The Public Site's documentation pages sanitize rendered content and carry the same browser security headers used elsewhere.

Version 1.2.0

MCP Server-Sent Events, external correlation IDs, and delegated On-Behalf-Of downstream authentication.

MCP over SSE

AI clients that expect a persistent server-to-client stream — rather than a JSON reply to each POST — can connect to the Runtime, invoke tools, and receive responses over SSE. The Runtime implements the Streamable HTTP transport of MCP specification 2025-11-25 in full, and keeps serving the deprecated 2024-11-05 HTTP+SSE transport for older clients.

  • /runtime/{tenantId}/{clientId}/mcp serves POST (JSON, or an SSE stream when the client accepts one), GET (the standalone server-to-client stream) and DELETE (session termination).
  • Sessions are established at initialize and carried in Mcp-Session-Id; an unrecognized session is always answered with 404 so the client re-initializes. Session ids are cryptographically random, and a request is accepted only when its tenant, client application and authenticated caller all match the identity that opened it.
  • Streams are resumable. Every frame carries an event id, and a client reconnecting with Last-Event-ID resumes on the stream that issued it and receives only what followed — never messages belonging to another stream.
  • The Origin header is validated on every request (the DNS-rebinding defense the specification mandates), and MCP-Protocol-Version is validated, assuming 2025-03-26 when absent. Malformed input is refused with an HTTP error status carrying a JSON-RPC error, replacing the previous 200-with-error-body behavior.
  • All transports feed the same request dispatcher, so the tool catalog, governance decisions and audit records do not depend on how a client connected.
  • Session state and message routing are shared across instances, so a multi-instance deployment needs no sticky sessions at the ingress — terminating a session on one instance closes the stream held by another, and a crashed instance's sessions cannot permanently consume a tenant's budget. Without a shared cache the Runtime falls back to single-instance mode and warns at startup.
  • Idle streams get a keep-alive every 15 seconds so proxies do not reap them; idle sessions are reclaimed, and a per-tenant session cap plus a dedicated rate limit bound stream growth. New configuration covers stream enablement, keep-alive cadence, idle timeout, session cap, queue depth, replay retention, SSE response preference and whether sessions are mandatory, validated at startup.

External correlation IDs

  • An MCP client may send an optional X-Correlation-Id; the Runtime stores it against the execution ID it generated and echoes it back on X-External-Correlation-Id. The Runtime always generates the execution ID itself rather than adopting an inbound header, so no caller can merge its audit records into another caller's execution trace.
  • The header is accepted only as a short opaque identifier — at most 128 characters, letters, digits and - _ . : / + = @ # — so it cannot carry free-form text. No prompt content is stored or processed.
  • Every governance audit record carries the caller's correlation ID, and both the governance and Call Flow explorers filter on it. All four client SDKs can send it, through an ambient provider callback or a per-call argument, and warn when the Runtime rejects the value rather than dropping it silently.
  • Each toolset chooses which correlation identifier goes downstream — the execution ID, the caller's, the caller's falling back to the execution ID, both on separate headers, or none — under configurable header names, validated on save and refused with a 400 if not a valid HTTP header field name. The policy applies identically to REST and SOAP tools, and existing toolsets are backfilled with the previous behavior.

Delegated downstream authentication

  • Downstream authentication profiles can select a grant profile — standard token exchange, Microsoft Entra ID On-Behalf-Of, or JWT bearer assertion — so the Runtime can obtain a downstream token in whichever shape the identity provider expects. Entra On-Behalf-Of lets an AI client reach Microsoft Graph, or any other Entra-protected API, as the signed-in user, with the downstream token never transiting the client. Existing token exchange profiles are unaffected.
  • For assertion-based grants the Runtime checks the caller's token audience before contacting the identity provider, reporting a mismatch by naming both what it saw and what it expected. A caller authenticating as an application rather than a user is refused with an explanation, or routed to the application's own credentials when the profile opts in. Provider rejections surface the returned error with an actionable hint — missing consent, wrong audience, expired assertion, invalid client secret — with the caller's token redacted out of the message.

Credential caching

  • Whether a cached credential is shared between callers is decided by the authentication strategy, not by the caching configuration, so the two can never disagree. A credential belonging to the signed-in user is always cached per caller; one that is the same for every caller is never fragmented, so an application with 2000 users acquires one credential rather than 2000 identical ones. Credential workflows are classified individually by whether they read the caller's token or identity.
  • Passthrough bearer authentication is no longer cached — it forwards the caller's own token and acquires nothing new. The cache scope selector offers only the scopes compatible with the selected strategy and explains the resulting isolation in words. The policy's time-to-live is now actually applied, as a ceiling on the credential's own expiry rather than an extension of it. Stored profiles are migrated automatically.
  • Governance audit records attribute a downstream call to the caller or the application from the same decision that drives caching, correcting cases where cached application credentials were recorded as delegated and credential workflows were always recorded as application even when acting for a user.

Version 1.1.12 — 2026 Q3

OData and Microsoft Graph correctness release. A tool built on an OData collection endpoint returned an empty object to the AI client even though the downstream call had succeeded and returned data. Collection responses are now modeled as the envelope OData actually sends, the paging link is exposed for the first time, and tools built on nested Graph paths such as a channel's messages can be invoked at all.

Changes in this release:

  • A tool built on a nested Microsoft Graph path — a team's channels, a channel's messages, a message's replies — now asks for every identifier its path needs. Previously the parent identifier was never offered as an input, so the tool could not be called at all; the failure appeared only when an AI client first tried to use it
  • Each identifier in such a path is now named for what it identifies — a team's channel messages ask for a team id and a channel id, not two fields both called id. Every Graph entity names its identifier id, so where a path did offer one, that single value was being used for every level and the call quietly fetched something other than what was asked for
  • Paths with a single identifier — a team by id, a user by id — are unchanged and need no attention
  • Action required: a Graph or OData API whose nested navigation endpoints were imported before this release must be re-imported; the affected tools cannot be invoked as they stand
  • A tool built on an OData or Microsoft Graph collection endpoint — listing users, groups, or any entity set — now returns the entities instead of an empty object; the call had been succeeding all along, but every response field was being read from the wrong place
  • Collection responses are modeled as the envelope the protocol actually sends, with the entities under value, rather than as a bare array; this covers entity set lists, navigation collections such as a user's direct reports, and functions and actions that return a collection
  • @odata.nextLink is now available as a mappable field, so an AI client can page a result the service truncated — previously there was no way to reach the continuation link, and a large result set silently ended at the first page
  • @odata.count is likewise available for endpoints called with $count=true
  • Single-entity reads are unaffected and were never subject to this defect
  • A field path can now address a property whose own name contains a dot, which is what makes the OData annotations above mappable; paths written before this release are unchanged and keep working
  • Action required: an OData or Graph API onboarded before this release must be re-imported and its mapping re-seeded to pick up the corrected response fields and the new paging fields. Existing mappings are not rewritten automatically, because the field paths in a published mapping belong to whoever authored it
  • This release carries no database schema change
  • Executable hosts, Portal Web, Public Site, and Runtime MCP server metadata are versioned 1.1.12-stable

Version 1.1.11 — 2026 Q3

Credential workflow release. A workflow-based authentication profile can now call a standards-compliant OAuth 2.0 token endpoint, which requires a form-encoded request that its HTTP step could not previously send, and can post and read the XML envelopes that legacy enterprise token services expect.

Changes in this release:

  • An HTTP request step in a credential workflow can now send its body as JSON (as before), as form data, or as raw content under a content type the author declares
  • Form bodies unblock the OAuth 2.0 token endpoint, so client_credentials, password, refresh_token, and token-exchange flows can be expressed as a workflow for the first time
  • Raw bodies cover SOAP and WS-Trust envelopes, plain text, and other vendor-specific formats; file uploads remain unsupported, as no credential flow needs them
  • A form body is edited as a list of named fields that can be added and removed individually, each bound to a static value, a variable from an earlier step, or a secret
  • Binding a field to a secret adds a visible Read secret step to the workflow and links the field to it, so every secret a workflow touches is read by an explicit step; selecting the same secret for a second field reuses that step instead of duplicating it
  • Values are substituted into a request body before it is encoded, and values placed into an XML body are XML-escaped, so a secret is always carried as a value rather than as request structure
  • Redaction of secrets in audit records and logs covers every encoded form a secret can take in a request, not only its literal value
  • A JSON body containing a value with a quote or backslash no longer produces a malformed request that fails the whole credential resolution
  • A parse-response step can now read XML using an XPath expression with declared namespace prefixes, and can extract either an element's text or the whole element for tokens that must be forwarded unchanged
  • XML responses are parsed with external content and definition loading disabled, so a downstream system cannot use its response to read local files, trigger outbound requests, or exhaust memory
  • Behavior change: a JSON request body that is not an object or array is now rejected when a workflow is saved, and the Portal reports an invalid body under the field instead of accepting it. Such a body was previously saved and sent as a bare JSON value, which no token endpoint accepts. Existing workflows continue to run, but one carrying an invalid body must be corrected before it can be saved again
  • XPath expressions and namespace declarations are validated when a workflow is saved rather than failing at the first tool call
  • Request bodies and XML responses are capped per deployment (defaulting to 64 KB), and this limit can be raised where signed assertions are large
  • This release carries no database schema change
  • Executable hosts, Portal Web, Public Site, and Runtime MCP server metadata are versioned 1.1.11-stable

Version 1.1.10 — 2026 Q3

Enrichment attachment security release. The prompt-injection scan that screens reference documents now decides what to do by how dangerous a match is, instead of rejecting an entire upload on any single match — and the model's own output is screened before it can reach a published tool description.

Changes in this release:

  • Reference documents are no longer rejected wholesale over a single pattern match: the most dangerous categories of match (instruction overrides, system-prompt reveal attempts, jailbreak phrasing, credential exfiltration attempts, and unsafe control characters) still block the upload, while lower-risk phrasing is redacted and the document is kept
  • A rejected upload now names the file and the categories of content that matched, instead of reporting only that the content "failed security scan"
  • The credential-exfiltration check now requires an external destination, so an API specification describing how a bearer token is forwarded to a downstream service can be attached; sending a credential to an outside URL or host is still blocked
  • Role-hijack style phrasing detection is more precise, so ordinary text like "you are a client developer integrating with this API" or "these fields act as filters" no longer triggers it
  • The prompt-injection scanner is more accurate at distinguishing genuine jailbreak attempts from incidental text, reducing false positives on ordinary documents
  • Redaction is applied before the extracted text is stored, so only the cleaned text is persisted
  • Redactions are reported on the upload response, in the governance audit event, and as a warning on the enrichment run
  • Suggestions returned by the enrichment model are now scanned before they are saved, and any carrying an injection are dropped with a warning naming what was removed — enriched descriptions are published to AI clients that, unlike the enrichment model, can act on instructions they read
  • Pattern severity thresholds for the prompt-injection scanner are configurable per deployment; an unrecognized pattern name now fails startup rather than being silently ignored
  • Severity alone decides the outcome for every prompt-injection match; a per-document match-count override that could relax that decision has been removed
  • The database migration for this release carries no schema change; attachment records written before it remain readable
  • The prompt-injection scan now has a bounded per-pattern timeout and fails closed if it is exceeded, so text crafted to exhaust the scanner cannot stall a request or pass as clean
  • The two attachment upload endpoints now reject an oversized body at the transport layer instead of buffering a large upload before failing the 1 MB attachment check
  • The per-file extraction limit is raised from 50,000 to 500,000 characters, so a full interface specification is no longer cut mid-document with its appendices never reaching the model
  • A document exactly at the extraction limit is no longer mislabeled "Truncated" in the enrichment run detail, and the truncation warning now reports how much text was actually dropped instead of repeating the limit back
  • Executable hosts, Portal Web, Public Site, and Runtime MCP server metadata are versioned 1.1.10-stable

Version 1.1.9 — 2026 Q3

Audit delivery and governance observability release. External audit delivery gets the corrections its retry model needed — terminal failure on the last configured attempt, a bounded critical health state, and a way to put failed deliveries back on the queue — and the Portal sharpens what an operator sees on the governance dashboards.

Changes in this release:

  • An external audit delivery is now marked failed on the last attempt its target allows, instead of being scheduled for one more attempt beyond the configured budget
  • A configured attempt budget larger than the built-in retry schedule is now honored in full rather than silently cut short
  • A permanently failed delivery raises its target to Critical for 24 hours from its last attempt, then decays to Warning until the delivery leaves audit retention, instead of holding Critical for a year
  • The critical-health window is configurable per deployment
  • Audit target health is derived in one place, so the Audit Delivery Settings page and the Monitoring Dashboard can no longer disagree about the same target
  • A permanently failed delivery can be put back on the delivery queue from the Portal: one row at a time, all failed deliveries of a target, or only those matching the filters currently applied to the target's audit events
  • Requeueing needs the Governance Manage role, is recorded as a governance audit event, and never re-sends a delivery that succeeded or one that is still being worked on
  • A requeued delivery becomes due immediately with a fresh attempt budget, and clears its target's Critical state once no failed delivery remains
  • A retrying delivery now shows when its next attempt is due, which was recorded but never displayed
  • A deployment whose compliance audit target is syslog, SQL Server, or PostgreSQL no longer records a false configuration error on every host start; the check previously looked only at REST-based targets
  • A disabled audit target now shows a single Disabled tag in its own color instead of an amber Warning health badge beside an amber Disabled badge; being switched off is deliberate, not a fault
  • The Monitoring Dashboard's activity trend now plots Allowed and Error alongside Total and Denied, in the same colors the outcome badges use, with a hover tooltip giving each day's exact counts
  • Trend series are also distinguished by dash pattern and marker shape, so the chart stays readable for red-green color blindness, and the chart now has its own validated colors for the dark theme instead of light-mode-only values
  • Auth profiles ask for each strategy's secret once: the duplicate "secret override" pickers for API key, Basic, SOAP UsernameToken, client credentials, and token exchange are gone, since they named the same logical secret as the profile's own secret reference
  • Client certificate (mTLS) profiles keep two secret fields, because the certificate file and its private key password are genuinely different secrets
  • Before re-saving an existing profile in the Portal, check whether its override and its secret reference pointed at different secrets — the runtime uses the override today, and saving drops it
  • The audit delivery health card reports Critical when any enabled compliance target is critical; previously every target had to be critical before the card showed it
  • Executable hosts, Portal Web, Public Site, and Runtime MCP server metadata are versioned 1.1.9-stable
  • No database changes; no migration is required

Version 1.1.8 — 2026 Q3

OpenAPI path-item parameter import fix. Contracts that declare entity keys once for a whole path — the idiomatic shape for generated specifications — imported without those keys, producing tools that failed on every call because the path value could not be supplied.

Changes in this release:

  • Parameters declared once for a whole API path are now merged into every operation of that path, with an operation's own declaration winning when it declares the same parameter itself, as the OpenAPI specification requires
  • Referenced path-item parameters now resolve correctly; only OpenAPI imports were affected, since OData derives paths and keys from a different source and SOAP operations have no equivalent placeholders
  • A significant share of paths in one real vendor contract (SAP Convergent Invoicing) were affected; their tools previously failed with a downstream error reporting a missing path parameter
  • Every import, whatever the protocol, now reports operations whose path placeholder the contract never declares as a parameter
  • Publishing a mapping whose endpoint has an unfillable path placeholder logs a warning identifying the mapping, endpoint, and missing parameters
  • The imported API's Import review panel now displays recorded import warnings, which were previously visible only during the import preview
  • The imported APIs list flags contracts that recorded import warnings with a count, so they can be spotted without opening each API
  • Mappings created before this release keep their incomplete parameter sets — re-import the API definition and regenerate the mapping to pick the parameters up
  • No database changes; no migration is required
  • Executable hosts, Portal Web, Public Site, and Runtime MCP server metadata are versioned 1.1.8-stable

Version 1.1.7 — 2026 Q3

OIDC metadata discovery and Runtime downstream-response hardening. External identity-provider probes now use the platform's centralized outbound-security boundary, and Runtime HTTP/SOAP invocations reject oversized responses before they can be fully buffered.

Changes in this release:

  • OIDC metadata requests are validated against the effective tenant/global outbound host allowlist before the request is sent
  • Every redirect destination is revalidated against the same allowlist as the original request
  • Discovery accepts only HTTPS authorities without embedded credentials, query strings, or fragments
  • Metadata responses must use a JSON content type, complete within 10 seconds, and remain within a 256 KiB streaming limit
  • Discovery and connection-test failures return a stable error code and a safe message; detailed network and parsing information remains in server-side logs only
  • Metadata discovery and connection testing require the Security Manage role
  • Response-size limits for outbound requests can now be enforced before a response body is fully buffered, rather than only after
  • Runtime HTTP and SOAP responses have an independent, configurable 16 MiB default size limit (Runtime:Downstream:MaxResponseBodyBytes)
  • Oversized declared responses are rejected based on their declared length; responses of unknown or streamed length are stopped as soon as they exceed the limit
  • Runtime callers receive a stable "response too large" error, and a corresponding metric records rejected downstream responses by protocol and cause
  • Authentication protection (failed-login tracking) is now applied asynchronously across Portal login, MFA, administrator unlock, Portal bearer, and Runtime bearer/API-key failure paths, so it adds no latency to those requests
  • Login-protection counters are updated atomically, so the lockout threshold stays accurate under concurrent attempts
  • Login and MFA enforcement fails closed if the protection store is unavailable, while alert notifications fail open only after the authentication request has already been denied
  • Account and IP identifiers used for failed-login tracking are stored as one-way fingerprints rather than in directly identifiable form
  • Persistence now separates global read-only visibility from cross-tenant write authority: a global read-only role can still view data across tenants but cannot save tenant-scoped changes, while the ability to write across tenant boundaries remains limited to the platform's highest administrative role
  • Vendor OpenAPI contracts with templated OAuth flow URLs (for example, a host and port left as placeholders) now import instead of failing with a URL parsing error
  • Unparsable URL fields are removed before reading and reported as import warnings; a remaining failure returns an actionable, stable error code
  • Non-structural import warnings no longer cause a whole contract to be rejected over minor quirks, such as server variables declared with empty defaults
  • Schemas that declare more than one possible shape for a field now resolve to a concrete type, so previously untyped fields (for example, a numeric field also allowed to be a string) now import with a proper type
  • Server-variable defaults are substituted into the stored server URL, and a still-templated URL is flagged as needing a configured downstream base URL
  • Generated tool names that exceed the length limit are shortened using a suffix derived from the full name, so entity-oriented contracts no longer fail to save over duplicate normalized names
  • Endpoint names already within the limit are unchanged, so existing mappings keep their tool names
  • Semantic enrichment no longer omits fields: payloads larger than one prompt are split across multiple prompts instead of being truncated, so a large contract cannot arrive with only its first fields named
  • Fields of a shared type (an OpenAPI component, OData type, or SOAP/XSD type) are enriched once and applied to every operation that uses it, cutting repeated work and preventing the same field being named differently in different operations
  • SOAP header and fault fields are now enriched; they previously became field mappings without ever being shown to the enrichment model
  • Field descriptions carry their owning type's identity, so the schema name the model is asked to return is grounded in real schema information instead of guessed
  • Suggestions from every prompt covering an operation are combined rather than replaced, and any field left without a suggestion is reported as a warning
  • New "Enrichment advanced settings" panel on the create-mapping and request-enrichment dialogs exposes prompt budget, fields per prompt, operations per prompt, and shared-schema enrichment, with platform defaults when left blank and validated bounds
  • Per-run enrichment settings are stored with the run, so an interrupted run resumes with the sizing it started with
  • Endpoint names proposed by the model are made unique automatically, so a proposal that names two similar operations identically no longer fails the whole enrichment run
  • A proposal that violates a business rule now fails the run with the reason recorded, instead of being retried indefinitely while the run sits at 100%
  • Executable hosts, Portal Web, Public Site, and Runtime MCP server metadata are versioned 1.1.7-stable

Version 1.1.6 — 2026 Q2

Downstream client certificate (mTLS) authentication. Administrators can now bind a downstream target authentication profile to a client certificate, so the Runtime authenticates to the downstream API via mutual TLS instead of a bearer token or header.

This release also makes semantic enrichment resilient to interruption. An enrichment run that stops partway — a worker crash, or a run outliving the message broker's delivery window — is now detected, re-queued, and resumed from the last completed chunk, instead of leaving the mapping locked with a frozen progress bar and no error.

Changes in this release:

  • New client certificate downstream authentication strategy, alongside the existing API key, Basic, bearer, OAuth, workflow, and SOAP strategies
  • Auth profile form: upload a certificate file directly, select the secret holding its private key password, and optionally enter an expected certificate thumbprint
  • Uploading a certificate creates a new secret in the existing secret store and selects it automatically — no separate binary-secret workflow to learn
  • Client certificates are presented on the TLS handshake for both REST/OpenAPI/OData tools and SOAP tools
  • Governance audit captures for client-certificate-authenticated invocations never contain the certificate or password material
  • Mapping editor: editing is now strictly limited to Draft/Proposed mappings (no more silent auto-clone-to-draft on Approved/Published), and "Cancel draft" is now "Cancel version," available from Draft through Approved
  • Mapping editor: semantic enrichment warnings are shown as their own alert instead of being folded into the change-summary text, and reference attachments can now be attached when creating a mapping proposal, not just when re-requesting enrichment
  • Trusted Identity Providers page redesign: a sectioned provider details view, a searchable claim mapping profile picker, a combined name-or-issuer search box, and refresh/loading indicators matching the rest of the portal
  • The built-in platform identity provider (used for device flow and web session sign-in) is now flagged as a system provider and shown with a "System" badge; it can no longer be edited or deleted from the admin UI
  • Claim Mapping Profiles page redesign to match: a sectioned profile details view (claims shown as badges instead of raw JSON), a redesigned enabled/disabled toggle, a debounced server-side name search, and the same refresh/loading indicators
  • The built-in "default" global claim mapping profile is now flagged as a system profile and shown with a "System" badge; it can no longer be edited or deleted from the admin UI
  • Credential Workflows page refresh: debounced name search, a searchable tenant filter, and refresh/loading indicators matching the rest of the portal
  • Credential Workflows step editor: bigger, easier-to-hit move-up/move-down/delete buttons; the final "build credential set" step's collapsed summary now shows extra headers/query parameters/cookies when no auth scheme is selected, and this step must now be the workflow's last step, enforced automatically by the editor
  • Fixed a shared searchable-dropdown bug where an open menu pushed surrounding layout taller and could render behind other panels, affecting every page using the searchable tenant/entity picker
  • Secret Store page refresh: debounced name search, refresh/loading indicators, and an "Add connection" button matching the other primary create actions
  • Secret Store grid: Store info, Created at, and Updated at are now combined into a single Details column placed after Tenant, matching the more compact activity-column layout used elsewhere
  • Secret details modal redesign: a sectioned view (store type and tenant scope badges, then a details grid) instead of a flat key/value list with raw JSON
  • Key Vault connection modal: the Enabled checkbox is now a labeled toggle card consistent with the enabled/disabled switches used on other pages
  • Outbound Allowlist page refresh: debounced host/name search and refresh/loading indicators matching the rest of the portal
  • Outbound Allowlist grid: the Description column was dropped in favor of showing the description beneath the entry name, and Subdomains/Status are now badges instead of plain text
  • Allowlist entry details modal redesign: a sectioned view (active/scope/subdomains badges, then a details grid, then the description) instead of a flat key/value list with raw JSON
  • Create/Edit allowlist entry modal: the Allow subdomains and Entry active checkboxes are now labeled toggle cards consistent with the enabled/disabled switches used on other pages
  • LLM Connections page refresh: connection name/status/provider filtering moved server-side with a debounced name search, plus refresh/loading indicators matching the rest of the portal
  • LLM Connections: new connection details view — a sectioned, read-only summary (scope/status badges, provider, credential handling, model profiles, tenant assignments, timestamps) opened from a new "View details" row action
  • LLM Connections: the tenant assignments "Remove" action is now a proper button instead of a link-styled button, and the connection/model profile Enabled checkboxes are now labeled toggle cards consistent with other pages
  • Client Applications page refresh: debounced name/client ID search and refresh/loading indicators matching the rest of the portal
  • Client application details modal redesign: a sectioned view (status badge, tenant, timestamps, then dedicated description and system prompt sections) instead of a flat key/value list with raw JSON
  • Create/Edit client application modal: the Active checkbox is now a labeled toggle card consistent with the enabled/disabled switches used on other pages
  • API Key management page refresh: debounced name/description search and refresh/loading indicators matching the rest of the portal
  • API key details modal redesign: a sectioned view (overview with status badge and timestamps, description, and claims shown as badges) instead of a flat key/value list
  • Edit API key modal: the Active checkbox is now a labeled toggle card consistent with the enabled/disabled switches used on other pages
  • Target Systems page refresh: debounced name search and refresh/loading indicators on both the target systems grid and the auth profiles grid, matching the rest of the portal
  • Target system and auth profile details modals redesign: sectioned views with status/strategy/tenant badges instead of a flat key/value list, and the auth profile modal now shows the strategy's additional configuration and credential caching settings as structured fields instead of raw JSON
  • Create/Edit target system and auth profile modals: the Active checkbox is now a labeled toggle card consistent with the enabled/disabled switches used on other pages, and the auth profile form's raw-JSON "Preview generated configuration" section has been removed
  • Tools Management page refresh: debounced mapping/toolset name search and refresh/loading indicators matching the rest of the portal
  • Tools Management: new read-only toolset details view — a sectioned summary (identity, default downstream settings and policy, client assignments, per-endpoint effective routing and access policy) opened from a new "View details" row action, available to every user regardless of manage access
  • Updated inline help content for the Client Applications, API Key management, Target Systems, and Tools Management pages to describe the new search, refresh, details, and toggle behavior
  • Monitoring Dashboard: the Reset filters and Search buttons now show icons, the audit table groups Category and Action into a single column, and the audit event detail view is now organized into sections (Overview, Actor, Request context) with status/category/action shown as badges instead of a flat field list
  • Monitoring Dashboard: audit event dimensions that contain JSON-encoded values are now pretty-printed instead of showing as a raw string
  • Monitoring Dashboard: CSV/JSON export now asks for confirmation before running when the matching result set is larger than the 200-row export limit, stating the total match count so a truncated export is never triggered by mistake
  • Updated inline help content for the Monitoring Dashboard to describe the new column layout, detail view, and export truncation confirmation
  • Enrichment Dashboard: the Reset filters and Search buttons now show icons, matching the Monitoring Dashboard
  • Enrichment Dashboard: added a Tenant column using the shared tenant display, and combined the Status and Progress columns into a single "Status & Progress" column
  • Enrichment Dashboard: added a selectable auto refresh interval (off, 3, 5, 10, 30, or 60 seconds); each refresh is now scheduled after the previous request finishes instead of on a fixed clock, so a slow request can no longer overlap the next poll
  • Updated inline help content for the Enrichment Dashboard to describe the new Tenant and Status & Progress columns and the auto refresh control
  • Call Flow page: the Reset filters and Search buttons now show icons, matching the Monitoring and Enrichment dashboards
  • Call Flow page: added a Tenant column using the shared tenant display, and combined the Type and Tool/Mapping columns into a single column
  • Updated inline help content for the Call Flow page to describe the new Type/Tool/Mapping and Tenant columns
  • Semantic enrichment now survives interruption: a run that stops because its worker crashed, or because the message broker withdrew the job for running longer than its maximum unacknowledged time, is automatically re-queued and resumes from the last completed chunk instead of restarting from the beginning
  • Enrichment runs report liveness on a timer while they are being processed, so a run that is merely slow is no longer mistaken for one that has stopped
  • A run whose worker is still running but stops making progress — stuck waiting on an LLM call that never returns — is now detected as hung and recovered, instead of appearing healthy indefinitely
  • Recovery signals the stuck attempt to stop before re-queueing the run, so an abandoned run stops consuming its LLM budget
  • Every completed enrichment pass is now recorded, so a resumed run only pays for the chunks it never finished — a 29-chunk run interrupted after 7 chunks resumes at chunk 8
  • A scheduled sweep releases enrichment runs that cannot be recovered, marking them failed with the number of chunks completed and unlocking the mapping, so a wedged run no longer needs manual database intervention
  • The sweep also reports how many enrichment runs are in progress and how recently each reported liveness, making a slow run distinguishable from a stuck one in the logs
  • The message broker's maximum unacknowledged-delivery time was raised from 30 minutes to 3 hours, so a long enrichment run against a slow LLM is no longer withdrawn mid-run

Version 1.1.5 — 2026 Q2

OData/CSDL + Microsoft Graph API onboarding. Administrators can now onboard OData v4 services — including Microsoft Graph — as first-class imported APIs alongside OpenAPI and SOAP/WSDL, with a shared preview/curation workflow that also now protects OpenAPI and WSDL imports from metadata explosion.

Changes in this release:

  • New OData contract protocol with Generic and Microsoft Graph import styles; CSDL metadata can be imported from uploaded content or a remote metadata URL
  • OData metadata is parsed into a full semantic model (entity types, complex types, enums, entity sets, singletons, navigation, actions/functions) before translation, so OData semantics survive rather than being flattened directly into the import model
  • Entity sets and singletons generate constrained create/read/update/delete operations that respect the service's own declared capability restrictions — read-only entity sets no longer get mutating tools generated for them
  • Bound and unbound actions and functions become first-class operations; single-hop navigation properties can be optionally included
  • The Microsoft Graph import style applies Graph-aware naming, permission hints, and conservative v1.0-only defaults
  • New standardized curation stage shared by OpenAPI, WSDL, and OData imports: an operation deny-list, an allow-list/explicit-selection mode, a tag/group allow-list, a path-prefix allow-list, a maximum-persisted-operation-count guardrail, and a mandatory explicit-selection step for oversized contracts, enforced before anything is persisted
  • New Portal import UX: an import-style selector, a "Preview operations" action showing the full candidate catalog with inclusion/exclusion reasons, and a selection checklist for committing only the chosen operations
  • Enum members, entity keys, and optimistic-concurrency tokens are now preserved on the imported schema instead of being flattened to plain strings
  • Endpoint identifiers remain stable across re-imports, so mapping version upgrades correctly preserve endpoint identity when a contract is re-imported
  • Structured logs, import metrics, and governance audit entries for every import mode, including the two new-version import endpoints, which previously had no audit coverage
  • Hardened CSDL metadata parsing against XML external-entity attacks; remote metadata fetches continue to go through the platform's outbound security checks

Version 1.1.4 — 2026 Q2

Device Authorization Grant (RFC 8628) plus browser-based runtime OAuth authorization hardening. AI agents and CLI tools can now authenticate and receive portal-equivalent credentials through operator-approved browser flows, and the browser authorization path now supports external-provider sign-in, MFA, and explicit consent.

Changes in this release:

  • Agents call a new initiation endpoint and receive a short user code (XXXX-YYYY) to display to the operator alongside a verification URL
  • A new /device page in Portal.Web lets operators look up the active session, sign in if not already authenticated, and approve or deny the request with a single action
  • The agent polls a dedicated token endpoint and receives an access token and refresh token once the operator approves
  • Runtime OAuth browser authorization now reuses the full Portal login experience instead of a separate minimal login page
  • OAuth authorization requests survive external-provider redirects, MFA verification, and tenant/context handoff so the flow can complete for accounts that require those steps
  • Already-authenticated operators must explicitly confirm runtime access before the authorization callback is completed
  • All device flow events — initiated, approved, denied, and token issued — are written to the governance audit trail with a shared session identifier for lifecycle correlation
  • Stale sessions (pending past expiry) are expired nightly; terminal sessions are purged after a configurable retention window by the existing data lifecycle job
  • Revoking a session — from the Portal UI, an administrator action, or an automatic response to detected refresh-token theft — now takes effect immediately against the Runtime, not just against future token refreshes. A revoked session's access token is rejected on its next use, on every host, rather than remaining valid until its own natural expiry

Version 1.1.3 — 2026 Q2

Semantic Enrichment Attachments. Administrators can now attach reference documents to an enrichment request to give the LLM additional context beyond the imported API definition.

Changes in this release:

  • Attach up to 5 reference files (.txt, .md, .pdf) per enrichment request with a combined size limit of 1 MB
  • Uploaded content is automatically scanned for prompt injection before the enrichment job is submitted; suspicious content is rejected before any processing begins
  • Reference documents are distilled once into a compact glossary, and only the entries relevant to each operation are injected into that operation's LLM pass — keeping large documents within the prompt budget instead of re-sending them on every chunk (configurable; falls back to verbatim injection)
  • File names, sizes, and content fingerprints are recorded on the enrichment run and visible in the run detail view
  • Attachment controls are available in both the standalone enrichment request modal and the new-version enrichment flow in the mapping editor
  • Files can be added across multiple picks and removed individually before submitting

Version 1.1.2 — 2026 Q2

Mapping annotation hint management. Administrators can now set MCP behavioral annotation hints per endpoint directly in the mapping editor, receive LLM-inferred hints through the semantic enrichment pipeline, and review proposed hints in the enrichment proposal panel before applying them to the draft.

Changes in this release:

  • Four per-endpoint annotation hints: Read-only, Destructive, Idempotent, and Open-world — each tri-state (Yes / No / Not set)
  • New "Endpoint annotation hints" enrichment target in the semantic enrichment request modal
  • LLM prompt and response schema updated to generate and receive annotation hints
  • Annotation diffs shown in the enrichment proposal panel alongside name and description changes
  • Inline help updated with annotation hint field documentation

Version 1.1.1 — 2026 Q2

MCP 2025-11-25 protocol compliance. The Runtime now advertises and implements the full MCP 2025-11-25 specification, including prompts, cursor-based pagination, and tool annotation hints on the wire.

Changes in this release:

  • Protocol version bumped to 2025-11-25 on the MCP initialize response
  • New ping handler returning an empty object as required by the specification
  • prompts/list and prompts/get expose toolset system prompts as user-controlled prompts (slash-command / menu items) alongside the existing resources surface
  • Tool annotation hints (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) emitted on the MCP wire for each tool; per-toolset annotation overrides configurable from the Portal
  • Cursor-based pagination on tools/list, resources/list, and prompts/list with configurable page sizes

Version 1.1.0 — 2026 Q2

API Onboarding Versioning release. Introduces API definition families that group multiple imported versions of the same downstream API, per-revision version labels and current-version designation, version compatibility reports, version-aware mapping draft creation that preserves endpoint IDs where operations match across API versions, and durable external governance audit delivery.

Changes in this release:

  • API definition families with multi-revision tracking and current-version promotion
  • Import new API version flow (URL and content) with version label and set-as-current options
  • Family Versions panel on API cards listing all revisions
  • Version compatibility view comparing two revisions with breaking-change classification
  • Delete protection for imported API definitions referenced by mapping versions
  • API-version-targeted mapping draft creation with endpoint identifier stability
  • External audit delivery fan-out with REST, syslog, SQL Server, and PostgreSQL compliance targets plus operational target monitoring/management in the Portal

Version 1.0.0 — 2026 Q1

First stable release. Full foundational platform including Portal, Portal API, Runtime, Jobs Worker, Gateway, and Database Migrator. Multi-tenant architecture, OpenAPI and SOAP/WSDL import, mapping proposal workflow, LLM-powered semantic enrichment, MCP toolset authoring, downstream authentication strategies, governance audit trail, area-based role model, and external identity provider federation.