AI Access Gateway

Security

How AAG is built, and what has not been proven yet

AAG is security infrastructure, so the useful version of this page is the one that separates what the product is designed to do from what an independent party has confirmed. Both halves are below, and the second half is the shorter one.

The enforcement model

Enforcement happens at the Gateway — a logical security boundary that belongs to exactly one of the businesses whose data is at stake.

A Gateway holds its own authorized identities, its own connections to external systems, its own credential relationships, its own policy and its own audit context.

A Gateway is a logical boundary, not a machine. It is deliberately not defined as a cloud project, cluster, container or virtual machine, so that the runtime can change without the security model changing.

A Gateway is a security boundary belonging to exactly one business, and a request authorized in one Gateway is not thereby authorized in another — including two Gateways owned by the same business. The ownership decision behind that is a walk over stored records rather than an inference from a name or a project layout. It is not topology-free, and AAG does not pretend otherwise: the caller identity the walk starts from is established by the cloud platform’s own access control, so the first hop rests on infrastructure and the rest does not.

Identity
Gateway traffic is not modelled as shared or unattributed access: a request that carries no session is refused before a handler is chosen, and every request has to be attributable to one specific caller. An identity is a machine identity here — a human reaches AAG through a different, separately authenticated path, and the two are distinct record types that are never collapsed. Attribution today is to the credential presented rather than to an independently verified caller, because the runtime trusts the platform’s own authentication of the identity in front of it.
Human identity
A person proves who they are to their own organization’s identity provider, which hands AAG a signed token rather than a password; AAG never receives one and so has none to keep. An identity is keyed by issuer and subject together — a bare subject is not an identity, and an email address is never used as the key, so the same address at two issuers is two identities and cannot be confused for one.
Session binding
One AI session is bound to exactly one Gateway, fixed when the session is issued and never mutated. Reaching a different Gateway requires a different session, the check is made server-side, and no policy may override it.
Discovery scope
A session can discover only the capabilities reachable through its own Gateway, even where the same caller is authorized elsewhere.
Connection cardinality
One connection binds exactly one external account, and a connection that is failing is not silently substituted with another one. A connection is never shared between Gateways.

How a request is decided

  • Fail closed, and deny by default where a policy governs. Where AAG is unable to determine identity, ownership, the intended account or the authorization answer with confidence, it denies rather than guessing or routing around the uncertainty — an unreachable database, an unreadable policy file, a stale or foreign snapshot and a request carrying no session all end in a refusal. On a Gateway configured with a policy, the absence of a rule permitting an action is itself a refusal. A Gateway deployed without one does not thereby permit more: the grant and capability checks still decide, but the policy layer abstains rather than denying, and that difference is worth knowing before reading “default deny” as universal.
  • The ownership chain is verified by reference. An authorization decision walks connection to Gateway to customer to organization against stored records. An identifier supplied by the caller — a gateway id, an account id, a binding id — is treated as a request and is checked against those records rather than believed: a mismatch is refused rather than silently overridden, so the record cannot describe a request nobody made. No caller-supplied name, label, path or hostname ever grants anything. Such values do participate in refusals, where the trusted side of the comparison always comes from the runtime’s own signed configuration or a stored row.
  • Reads and mutations are separate grants. Every capability is classified as a read or as a mutation, one by one. Permission to change something is not inferred from permission to read it, and a capability carrying no classification is treated as a mutation rather than as a read.
  • Administration and data access. Where today’s estate stands against that rule is set out in the honest limitations, and it is the largest gap on this page.

Credential custody

What an AI system holds while it acts on an external account, and what it does not.

  • No AI caller receives credential material — no token, key, secret, certificate or redeemable handle — at any permission level.
  • A connection holds a reference to protected storage. Configuration objects do not carry secret material inline.
  • Credential material is submitted through one dedicated path that accepts nothing else, and the service that receives it holds an identity which can add a version and cannot read one back — so it is not displayed again after it is entered, and the component that placed it cannot retrieve it. Where AAG needs a credential from a particular person, it records who is being asked, against the requirement being satisfied; AAG sends nothing — no mailer exists in the product — so a message that says it is an AAG invitation did not come from AAG. The material itself always returns through the same dedicated path, and never through an email thread, a chat, a ticket or a screenshot.
  • Credentials are not pooled across boundaries. Two connections in two Gateways do not share a credential relationship, even when they point at the same external account.
  • Credential material is screened out of audit records before they are stored, rather than when they are displayed. The screen is a denylist: it catches shapes that name themselves, and AAG does not claim it is exhaustive. A secret with no shape of its own is not distinguishable from any other high-entropy string, and the shapes it admits are written down in the code’s own tests rather than left to be discovered.

Credential material is held in Google Secret Manager and encrypted at rest with a customer-managed key. The separation that key buys is by principal rather than by project: the grants on it are to Google’s own Secret Manager and Cloud Storage service agents, so neither a Connector runtime nor the path that accepts new material may use the key directly. A Connector runtime is granted read access to exactly one secret — its own Credential Binding — and the path that accepts new material may add a version and may never read one.

Audit and evidence

  • Security-relevant activity is recorded: access decisions, connector executions, credential changes, policy changes, lifecycle changes and administrative actions.
  • Denials are evidence, not noise, and they are not sampled away: a denial produces an event carrying actor, scope, action and reason category. Once a request has been matched to this Gateway and its token verified, every decision after that point — allowed or denied — is recorded and attributable. Before that point there is no actor to name, and a request refused there leaves no record in this chain at all. That is deliberate rather than missing: the identity presented may belong to a different business, and writing it into this business’s evidence would disclose one customer to another. The consequence is worth stating plainly, because it bounds what the chain can be used for: traffic refused at the door is counted in operational logs and does not appear in the audit evidence a customer is given. Concretely, that is a request naming a host this Gateway does not serve, or carrying a token for another Gateway or no readable token at all.
  • Audit records are append-only. A correction is a new event; records are not edited or deleted to change what they say. The evidence store enforces that rather than promising it: a write refuses to overwrite an object that already exists, the identity that writes holds create-and-read and no delete, and the retention policy on this estate has been locked, which puts shortening it beyond an operator and beyond Google. That lock runs for 400 days rather than forever. Evidence is written once per name under a precondition that refuses an overwrite, and sits under a retention policy. Reads of that evidence are not recorded today, because Data Access logging is off across the estate — so AAG is unable to show you who looked.
  • Control-plane audit logs are retained for 400 days. That is the retention period governing audit evidence, and it is not a general schedule: other periods exist for operational reasons — a database point-in-time-recovery window, for one — and no product-wide retention schedule has been set or is published here.
  • AAG is designed to produce a security evidence package scoped to exactly one customer, covering that customer’s own posture: which external systems are reachable, which callers may perform mutations, which people hold administrative access, credential health and denial activity.
  • An evidence package must not disclose the existence of any other customer — not in a name, an identifier, a count or a total — and must not contain credential material or business data.

Data handling

  • AAG’s request path is not a store of customer business data: a Gateway does not cache what a provider returns, transform it for later or replay it. An audit record describes that a request happened and how it was decided rather than what it returned — with one exception on the failure path, where the provider’s own error sentence is copied into the record verbatim so that a denial can be explained, and a provider that puts data into an error message therefore puts it into the record. One tool is a deliberate exception and it is not the Gateway. The discovery tool, run against an advertising account during onboarding, writes what it reads to files on the machine that runs it — account names, spend over the last 30 and 90 days, and the email addresses and roles of the people who hold access — so that a run stopped by a provider quota can resume instead of starting again. It leaves three files, and its redaction setting masks addresses in the one it renders for reading and in neither of the other two. Separately and durably, AAG stores the identifiers and display names a provider gives for the accounts a Gateway is configured against, because that is the configuration itself.
  • The control-plane database holds product records — organizations, Gateways, connections, identities, roles, lifecycle state. It does not hold credential material, and it is not where business data lives.
  • Where a security or privacy transformation is configured — classification, redaction, pseudonymization — it must be policy-governed, auditable and attributable, and it must not silently change what a result means. Where none is configured, results pass through unmodified.

AAG’s platform infrastructure is deployed in a single Google Cloud region in the United States, on multi-zone managed services. Three things sit outside that region. Database backups and Terraform state are held in Google’s United States multi-region, so they leave the region and stay in the country. The public DNS zones that make a Gateway reachable by name are served by Google’s global name servers, which leaves the country as well: what those zones publish is the hostnames themselves and no customer content. Per-customer data residency is not offered. The full list of third parties involved is on the subprocessors page.

No customer-facing Gateway is running in production yet, so no customer business data is being processed anywhere today. No code enforces that; it is a statement about the live estate on the date at the top of this page. Everything above describes required behaviour of a system that is being built, not a report on traffic it is carrying.

What is verified, and what is not

This is the section most security pages leave out. It is here because a claim a reviewer can falsify costs more than the claim was worth.

Independent assurance AAG holds as of the date on this page.
AssuranceStatus
SOC 2 (Type I or Type II)None. No report exists and none is in progress.
ISO/IEC 27001None.
HIPAA or PCI DSS attestationNone.
Independent penetration testNone performed.
Cyber liability insuranceNot in place.
Customer referencesNone to offer.
Service level agreementNone. No uptime figure, response time or restoration target is set or implied anywhere on this site.

The controls described above are required product behaviour: what the specification obliges the implementation to do. AAG has run an internal audit of the implementation against that specification, and the honest summary of it is that a well-built single-boundary runtime with real authorization logic exists, while a great deal of what the specification requires — particularly in provisioning, persistence and credential handling at scale — is not built yet.

Nothing on this page has been verified by an outside party. AAG holds no security certification, no independent audit report and no penetration-test result, and nothing on this site should be read as one. No code enforces that and none could — it is a fact about the world, and the way to test it is to ask for the report and be told there is none. A documented requirement is not evidence of a working control, and this page does not present one as the other.

Honest limitations

These are open risks AAG has written down rather than worked around. They are stated here in the same words used internally.

Connector code sits inside the credential trust boundary

Integration code with credential access and outbound network access can exfiltrate that credential regardless of every other control described here. Egress restriction is declared per integration and compiled into a rule above a blanket refusal — with the limits of that rule in the next entry, which is part of this same risk — and general sandboxing and execution isolation are architecture that is not yet designed. This is the largest open risk in the model, and who may author an integration is still an open decision.

The egress rule enforces on addresses, not on names

The Connector Type declares its destinations in its manifest — for Google Ads, exactly two — and the firewall rule is built from that declaration, above a default deny. But an FQDN firewall object resolves a name periodically and then enforces on the resulting addresses, not on the name, and Google API hostnames share address space. So against a Google-hosted provider this rule does not separate this integration’s own Google API from any other Google API. What it does still do, and what matters against exfiltration, is deny every non-Google destination on the internet.

The same mechanism has a second consequence, stated here because it is the same mistake to read the rule as a list of names: a direct connection to an address that an allowed hostname itself resolved to is indistinguishable at layer 3, so the rule does not tell one from the other.

What this does not weaken is the credential boundary. One integration’s runtime reaching another’s provider still does not gain access to that other credential, because credential access is enforced by secret-store authorization and not by a network rule. The two controls are independent on purpose, and this is the one that degrades where address space is shared.

Administrative separation is not enforced against AAG’s own operator

Administrative authority is not designed to confer client data access, and that separation is not yet enforced against AAG’s own operator. AAG runs on a single-operator estate: that operator holds project-owner rights on every AAG project, including the projects holding credential secrets, and can therefore read them. No product code path grants this — it is cloud-platform administration, and it is the state a solo-founder estate is in before separation of duties exists. The audit chain’s checkpoint signing key sits inside the same authority: the grant naming the ingestion service is one binding among any others that may be added, so the person who can read a credential can also give themselves the power to sign checkpoints, or destroy the key and leave every past signature unverifiable. What is built and proven is the containment: one secret per credential binding, one reader per secret, an intake identity that can write a credential and never read one back, and an adversarial suite that asks each deployed identity to cross those lines and records the refusal. That suite tests the deployed services and does not test the administrator. What is not built is any control that stops an administrator from granting themselves credential-read or checkpoint-signing authority in their own name.

Canon carries this rule as an invariant and lists it as pending enforcement, with its closing mechanism named and not yet written. A break-glass path is an open decision, and none may be built while it is open. Data Access logging is off across the estate, so a read of a credential would also leave no record — which is why this is stated here rather than described as a designed exception.

Credential material is retained, not destroyed

Revocation makes a credential unusable rather than destroying it. It is something an AAG operator runs, not something you can trigger yourself: a command run from a checkout by a named person sets the Credential Binding to revoked and removes the Connector Executor’s read grant. That removal is checked rather than assumed — the secret’s access policy is read back afterwards, and if any reader remains, or the policy cannot be read at all, the command says so instead of reporting success. What it does not do is revoke anything at your provider: there is no implementation of that on this estate, in any form. The stored secret and its earlier versions are retained throughout, and destruction on offboarding is specified and is not built. Treat credential material you have given AAG as retained until you also revoke it at the provider, which is the only step that ends the provider’s trust in it.

This is a capability gap, not a policy choice. There is no destroy path in the codebase at all: the component that writes credential material can create a secret and add a version, and has no remover, while the database schema uses restricted deletes that actively refuse a cascading row delete. Offboarding destruction is specified, tracked as outstanding work, and unbuilt.

The credential screen on audit records is a denylist

Credential material is screened out of audit records before they are stored, rather than when they are displayed. The screen is a denylist: it catches shapes that name themselves, and AAG does not claim it is exhaustive. A secret with no shape of its own is not distinguishable from any other high-entropy string, and the shapes it admits are written down in the code’s own tests rather than left to be discovered.

An entropy or length heuristic was measured and refused, because it flags every hash and artifact digest the audit record is made of. So the limit is stated instead of being papered over. A passing test block in the codebase enumerates sixteen cases, of which thirteen are named as shapes the screen ADMITS: among them a secret carrying no recognisable prefix, an intact credential split across two fields, an encoded one, and a provider prefix that has not been added to the table yet.

A capability declaration is not self-validating

An integration declares which of its capabilities change data. Detecting one that mislabels a change as a read requires review or behavioural verification that is not designed yet.

Session revocation is bounded, not instantaneous

What is built refuses new admissions after revocation; aborting a request already in flight is specified and not met. The gap is real and is stated rather than rounded down to zero. A short session lifetime is not revocation.

AAG has no reach into what a model already retained

AAG can bound which Gateway a session reaches through AAG. It has no reach into what a third-party model has already retained, so revoking a session ends the operations that come after it and is not context destruction. The session is checked once as a request enters, which means a request already under way finishes: the bound on that is the six-second ceiling on upstream work, not an instant stop. This is a stated limit of the product rather than a gap awaiting a fix.

A provider’s authority is a ceiling

A provider’s own authority is a ceiling AAG works below. AAG has no way to grant access a provider has refused, no way to override a provider’s own controls, and no defence against a provider that is itself compromised — and it does not claim otherwise. The achievable goal is that a provider’s problem does not become an isolation or a custody problem.

Least privilege bounds a subverted caller; it does not detect one

AAG constrains what an authorized caller may do, not why it decided to do it. A manipulated agent acting within its grants is acting within its grants.

There is no policy simulation

No “what would this configuration allow” capability exists. Reviewing intent against effect is a human task today.

No general schedule for how long records are kept

Control-plane audit logs are retained for 400 days. That is the retention period governing audit evidence, and it is not a general schedule: other periods exist for operational reasons — a database point-in-time-recovery window, for one — and no product-wide retention schedule has been set or is published here.

Reporting a vulnerability

Report anything you believe is a security issue to jose@aiaccessgateway.com. Include enough detail to reproduce it. There is no bug bounty and no published response-time commitment, because neither has been set — saying otherwise would be the kind of claim this page exists to avoid.

AAG will not pursue legal action over good-faith research that avoids privacy violations, service degradation and data destruction. The machine-readable version of this is at /.well-known/security.txt.

All contact routes