inhold Book a call

Reviewer packet

Inhold answers for a security reviewer, on one page

Inhold's 20 reviewer answers, its known gaps and its 164.312 map, laid out to print or save as a PDF from your browser.

Last checked 31 Oct 2026, written by Vivek

Inhold is being built. No customers yet. Repo goes public 9 Nov 2026.

Status

Where each answer stands

16 in v0, 3 designed, 1 gap

#QuestionAnswerStatus
Q1Where does the agent's memory live?

In the customer's AWS account, in Postgres in private subnets, encrypted with their KMS key.

v0 uses SQLite on one machine. A database adapter is in place so Postgres can sit behind the same service; Postgres itself is in build. The AWS install is designed, in build.

designed, in build
Q2Does any data leave our account?

Inhold has no telemetry, licence server or update check. On a laptop the running service makes no outbound calls. In AWS mode, built in code and not yet run on real AWS, it calls only AWS services in your account, through your VPC endpoints: STS once per agent sign-in, and S3 and KMS (kms:GenerateMac, kms:VerifyMac) to write and check its audit anchors. The install's endpoints for ECR, CloudWatch Logs and Secrets Manager serve the container platform. No call ever goes to Inhold the company. The install checker, inhold doctor, reads AWS APIs when you run it. Your vendor's agent receives whatever policy lets it read, so if that agent runs in the vendor's account, that data leaves yours.

The CI egress test runs the demo with outbound connections blocked. It also checks that agent sign-in attempts the regional AWS STS endpoint, with that connection blocked by the test. It does not test a real STS response or prove the AWS network controls. The network controls ship with the AWS install.

in v0
Q3Can the vendor or Inhold staff read our data?

Inhold staff have no account in your install and no entry in your bundle. The vendor's agents read only what your bundle grants them, every read is logged, and those grants can include PHI.

in v0
Q4Who decides what an agent may read?

Your policy bundle, a JSON document your team owns. Every read is checked on actor, purpose and data label. After the first boot, changes take effect only through the policy API, which logs them.

in v0
Q5How is minimum necessary enforced?

Each call runs under a purpose. Search leaves out labels outside it and logs the filter it applied; a direct read of such an item is refused and logged.

in v0
Q6Can an agent claim a purpose it is not registered for?

No. Identity is fixed at authentication. A requested purpose is refused unless the bundle registers it for that identity, and on MCP the purpose is fixed for the session.

in v0
Q7What gets logged?

Every policy decision, allowed or denied: who, which action, which object, which labels, which purpose, which policy version, which engine hash and which session id. One audit chain is kept across connections.

The session id groups one agent run's rows and is never used in a decision. The MCP server sets one per process; over REST the caller sends it.

in v0
Q8Can the audit log be altered?

Not by the application: rows are append-only and hash-linked. Anchors outside the database are written when the store is created, every 100 rows and at each export, and are signed when an anchor key is configured. On one machine they are kept as write-once files on the host and in every pack. Verification fails on truncation or rewrite below an anchor, and refuses to pass with no anchor.

This detects a rewrite only if the admin cannot also reach the anchors. In v0 on one machine the anchors sit on the same host, so keep each pack you receive and check the next one against it. An S3 Object Lock store, signed with a KMS HMAC key, is built in code and inhold anchor writes the heads there. It has not been run against a real AWS account. Rows after the newest anchor are not covered, and read-only gateways leave heads pending until inhold anchor runs.

in v0
Q9How do we see denied attempts?

Deny rows are in the audit export with the reason, and the summary counts them by action.

in v0
Q10How is PHI identified?

At write time, local detectors label MRN, date of birth, ICD-10, NPI, member id, SSN, email and phone, and an optional local model labels person names. Nothing leaves the machine. Callers can add labels, never remove them.

Person names need the optional local name model, and on synthetic test sets it still misses some. Addresses and free-text dates are not detected. Sending a subject with each patient write makes the item PHI whatever the tagger finds.

gap
Q11What happens when a nurse corrects the agent?

The correction is stored with a diff and becomes a draft skill. A named approver must approve it before any agent uses it.

in v0
Q12Who can change the policy?

Only roles granted policy change in the bundle. Each change is logged with the new bundle hash.

in v0
Q13Which policy version made a given decision?

Every audit row carries the SHA-256 of the active bundle, along with the engine hash and the session id.

in v0
Q14How is data encrypted?

In progress. The AWS install kit encrypts at rest with your KMS key and serves TLS inside your VPC. It is not shipped.

On a laptop, encryption at rest is whatever the host disk provides, and the demo serves plain HTTP on 127.0.0.1.

designed
Q15How do people and agents sign in?

People use OIDC with a pinned JWKS and one stable identity claim, oid by default. Agents use an AWS IAM role with a presigned sts:GetCallerIdentity request. The mTLS fallback is not built.

OIDC is tested with generated signing keys and IAM sign-in with a stand-in for STS, not yet against a real identity provider or AWS account. Static tokens are laptop-only. On REST and MCP over HTTP they need a flag and are refused in AWS mode; stdio MCP still uses a static token with no flag.

in v0
Q16Does Inhold call an AI model with our data?

No. Inhold makes no model calls over the network. The only model inside it is the optional local name detector, which runs from files on disk. Any later feature that calls a model would call your endpoint, off by default, with each call audited.

Which model your agent calls, and under what agreement, is between you and your customer; Inhold does not control it.

in v0
Q17Is Inhold a HIPAA business associate?

Our position is no for the software alone, because the software sends us nothing and we hold no account. Support that needs access to PHI would be under a BAA.

Not yet reviewed by a lawyer.

designed
Q18Which HIPAA safeguards does this cover?

The control map is in v0 and covers parts of 164.312(a) to (e) and minimum necessary. Six rows are in v0, two are designed and one is a gap; see the HIPAA map.

Inhold maps what it does to eight lines of 45 CFR 164.312 and to the minimum necessary standard. It does not yet map emergency access, automatic logoff or the (e)(2) specifications. The map is a draft for your reviewer, not legal advice.

in v0
Q19What threats did you model?

A STRIDE model of the gateway, store, policy and audit, including prompt injection that tries to read another purpose's data.

Not yet reviewed by an outside security tester.

in v0
Q20How do we know the pack is complete and unaltered?

MANIFEST.json lists each file's SHA-256, the chain head, the export anchor and the policy hash, but it is unsigned. inhold verify-pack checks the chain against an earlier pack you kept, so a pack cannot vouch for itself and your first pack is the one you start trusting from.

in v0

Known gaps

What is not built, or not good enough yet

gapAWS install

v0 runs on one machine with SQLite. A database adapter is in place. The Terraform module, Postgres, KMS and private networking are in build (status: designed).

Before first pilot

gapSign-in not tried against real services

OIDC is tested with generated signing keys and IAM sign-in with a stand-in for STS, not yet against a real identity provider or AWS account. Static tokens are laptop-only. On REST and MCP over HTTP they need a flag and are refused in AWS mode; stdio MCP still uses a static token with no flag.

Before first pilot

gapShared identity through OIDC groups

Every principal is a named agent or person in the bundle. People mapped by OIDC group share one principal, so list a person under oidc_users to get a unique audit identity.

Not scheduled

gapContent integrity

Skills are versioned and record the corrections they came from, and corrections carry a diff. Memory bodies have no content hash, so a change made directly in the database is not detected.

Not scheduled

gapSelf-approval

A person with the approver role can approve their own correction. The demo does this.

Not scheduled

gapChain rewrite by a database admin

Anchors catch a rewrite below the newest anchor only if the admin cannot also reach them. They are signed when an anchor key is configured. In v0 on one machine they sit on the same host, so keep each pack and check the next one against it. An S3 Object Lock store, signed with a KMS HMAC key, is built in code and inhold anchor writes the heads there. It has not been run against a real AWS account. Rows after the newest anchor are not covered, and read-only gateways leave heads pending until inhold anchor runs.

With the AWS install

gapA failed commit on a refusal

If the database refuses to commit a deny, the call returns 500 and the access is still refused, but the refusal leaves no audit row.

Not scheduled

gapHard delete

A delete marks the item as deleted and hides it from reads and search, but the row stays in the database.

Not scheduled

gapNames in free text

The optional local name model misses some patient names on synthetic test sets, and addresses and free-text dates are not detected.

v0.1

gapRate limits

No general request rate limiting or denial-of-service controls in v0. Agent sign-in has limits on failed STS checks and concurrent STS calls.

Not scheduled

gapImage signing and SBOM

There are no release images yet. Signing and an SBOM are planned with the AWS install.

With the AWS install

gapOutside review

No penetration test and no outside security review yet. The threat model is our own.

Not scheduled

gapSOC 2

Inhold the company has no SOC 2 report. A SOC 2 Type II audit is planned for 2027.

Planned 2027

gapBusiness associate position

Our position on Q17 has not been reviewed by a lawyer.

Before first pilot

HIPAA Security Rule

45 CFR 164.312, line by line

SafeguardWhat Inhold doesEvidence fileStatus
164.312(a)(1) Access controlDeny-by-default policy on every read, write and delete, decided on actor, purpose and data label.policy/active_bundle.json; policy/inhold.rego (a readable mirror of the Python evaluator, kept equal by a CI test)in v0
164.312(a)(2)(i) Unique user identificationEvery principal is a named agent or person in the bundle. People mapped by OIDC group share one principal, so list a person under oidc_users to get a unique audit identity.policy/active_bundle.json; audit/audit_events.jsonl (actor_id)in v0
164.312(a)(2)(iv) Encryption and decryptionRDS and S3 encrypted with the customer's own KMS key. Requires the AWS install, in build.DATA_FLOW.md, Keysdesigned
164.312(b) Audit controlsOne audit row for every policy decision, allowed or denied, including admin actions and exports.audit/audit_events.jsonl; audit/summary.jsonin v0
164.312(c)(1) IntegrityAudit rows are hash-chained and append-only. The pack includes a verification result. In the demo pack it reads ok: true, with anchors signed by a synthetic demo key.audit/chain_verification.jsonin v0
164.312(c)(2) Mechanism to authenticate ePHISkills are versioned and record the corrections they came from, and corrections carry a diff. Memory bodies have no content hash, so a change made directly in the database is not detected.audit/audit_events.jsonl (write rows); memory content hashes are absentgap
164.312(d) Person or entity authenticationPeople use OIDC with a pinned JWKS and one stable identity claim, oid by default. Agents use an AWS IAM role with a presigned sts:GetCallerIdentity request. The mTLS fallback is not built. OIDC is tested with generated signing keys and IAM sign-in with a stand-in for STS, not yet against a real identity provider or AWS account. Static tokens are laptop-only. On REST and MCP over HTTP they need a flag and are refused in AWS mode; stdio MCP still uses a static token with no flag.Sign-in tests in the repo; DATA_FLOW.md, Identity, still lists IAM sign-in and MCP over HTTP as unbuilt and describes an unbuilt mTLS fallback.in v0
164.312(e)(1) Transmission securityPrivate subnets, TLS inside the VPC, AWS calls only to STS for agent sign-in and S3 and KMS for anchors, through VPC endpoints, and no calls to Inhold. Requires the AWS install, in build. The statement describes the AWS design; the security group it mentions ships with the install.deployment/egress_statement.md; DATA_FLOW.mddesigned
164.502(b) Minimum necessaryEvery call runs under a purpose: named in the REST request, or fixed for the session on MCP. Search leaves out labels outside it and logs the filter it applied; a direct read of such an item is refused and logged.policy/active_bundle.json; audit/audit_events.jsonl (deny rows)in v0

Printed from the Inhold site. Status checked 31 Oct 2026. Inhold is being built and has no customers. Nothing here is a certification.