Target Registry authoring reference
How a registry package is put together - parameters, operations, the deployment flow, conditions, state, PowerShell and rollback - and how to start one from JSON or with an AI assistant over MCP.
This page is for publishers. It describes the model behind Store > Target Registry >
New Registry Target (schema registry.aethercert.com/v2). If you only install
packages, Target Registry is all you need.
The parts of a package
| Part | What it is |
|---|---|
| Parameters | What the installer fills in per deploy target: text, number, yes/no, a list of texts, or a secret. |
| Connection | Where REST and TLS operations connect - a host (optionally a port and "accept a self-signed certificate"), a local socket, or nothing. |
| Authentication | How the agent signs in once for every REST operation: HTTP Basic, an API key, OAuth2 client credentials, or a session login. |
| Operations | What the target can do. Each has a name, a capability (what it does), and one way of running: REST, file, TLS check, service, or PowerShell. |
| Deployment flow | The steps that run, top to bottom. One operation can run in more than one step. |
| Rollback | Optional steps that try to undo a failed deployment. |
Two things are derived for you and never typed: the package's capabilities (the union of its operations' capabilities, a label for people browsing the Store) and its permissions (exactly what the operations need - publishing refuses both less and more).
References
Values reach an operation through references written as {{ root.path }}. There are no
expressions or functions - a reference is replaced by its value, nothing more.
| Root | What it holds |
|---|---|
config.<key> | A parameter the installer filled in. |
secret.<key> | A secret parameter. Only usable in authentication, REST headers, bodies and query values, and secret script parameters - never in a path, a file, a condition or an output. |
state.<key> | A value an earlier step wrote (see State). |
certificate, chain, privateKey, pfx | The key material being deployed (PEM, .base64, .derBase64; pfx and pfx.password). Using one gives the operation that material - and nothing else. |
job.* | Facts about the job: id, commonName, domains, isRenewal. |
A secret never appears in the package itself - only the reference does. The installer's value is stored encrypted and redacted from every error.
State
An operation can declare outputs: values it picks from a REST response ($.id,
$.data.name, or $status for the HTTP status code) or from the JSON object a PowerShell
operation prints on its last line. Each output is written to state.<name> after the step
succeeds, and later steps read it - in a path, a body, a condition or a PowerShell
parameter.
A step can only read state from steps above it; the editor offers nothing else and publishing checks it. A state value that was never written - because the step that writes it was skipped - is empty.
Conditions
A step can run only when a condition holds: one value, one comparison. A step whose condition is false is shown as skipped and the flow continues.
| Value | "has a value" | "is empty or not set" | "is" "" / "is not" "" |
|---|---|---|---|
| not set / never written | no | yes | is "" |
"" (empty text) | no | yes | is "" |
"x" | yes | no | is not "" |
false | yes | no | compared as "false" |
0 | yes | no | compared as "0" |
empty list [] | yes (present, but empty) | no | not allowed - use "contains" |
["a"] | yes | no | not allowed - use "contains" |
- "is on" / "is off" exist only for yes/no parameters; a value that is not set counts as off.
- "contains" exists only for lists, and is false on an empty or unset list.
- Recommendation: for an optional text where the content matters (a chain path, a service name, a previous thumbprint), use "is not" with an empty value rather than "has a value". It says exactly what you mean.
PowerShell scripts
Every PowerShell operation is a script your package defines - community publishers
included. Declare each value the script reads as a parameter (type, required, allowed
values, pattern, length) and pass values with with: each value is a literal or exactly
one reference, checked against the parameter before the script starts. Nothing is
ever pasted into script source. The operation needs the local.powershell: script
permission, which the editor derives for you.
Your script runs wherever the installing organization's registry policy allows your package. Community packages are off by default in every organization, so a community package reaches organizations that chose to enable community targets.
A script reads its parameters as $env:AC_PARAM_<name>. With the certificate as material
it also gets $env:AC_CERT_THUMBPRINT, $env:AC_CERT_COMMON_NAME and $env:AC_CERT_SANS;
with certificate and private key, $env:AC_PFX_PATH and $env:AC_PFX_PASSWORD - a
temporary PFX file with restricted access that is deleted afterwards, even when the script
fails. Print outputs as one JSON object on the last line:
$ErrorActionPreference = 'Stop'
Set-AdfsSslCertificate -Thumbprint $env:AC_PARAM_thumbprint
@{ thumbprint = $env:AC_PARAM_thumbprint } | ConvertTo-Json -CompressWhat the script boundary does and does not promise
The script arrives on standard input, never on the command line, and its source contains no secrets. Values in environment variables are still readable inside the process and by sufficiently privileged processes on the host (SYSTEM, administrators, debuggers). The host is trusted - this narrows what a package can touch, it does not hide anything from the machine's own administrators.
Rollback
Define a rollback when the target has a reliable previous state to return to - for
example the certificate an IIS binding used before, which iis.setBindingCertificate
returns as previousThumbprint.
- It runs only when the deployment fails after at least one step succeeded.
- Its steps run in order; a failing one does not stop the others.
- It can read every state value the deployment wrote. Guard each step - e.g. run the
restore only if
state.previousThumbprint"is not"""- so it does nothing when there was nothing to restore. - It is best effort, not a transaction. Nothing is guaranteed to come back, and the
deployment's own error always stays the job's result. The rollback outcome
(
succeeded,partial,failed) is logged next to it. - Order the deployment so destructive steps come last - remove the old certificate only after the new one is bound and verified, so a rollback still has something to bind.
Leave the rollback empty when there is no reliable previous state; a rollback that guesses is worse than none.
Capabilities
Pick a capability from the catalogue (certificate, private key, binding, configuration,
service, deployment) or name your own, such as windowsRole.certificateBind. The
catalogue's own namespaces only accept catalogue names, to catch typos. A capability is a
label: what an operation may do is decided by how it runs, the material it declares and
its permissions - never by its capability name.
Starting from JSON
New Registry Target offers three ways to start:
- Create manually opens the form editor described above.
- Import file opens a manifest
.jsonfile. The file is read in your browser; nothing is uploaded until you save. - Paste JSON takes a
DeploymentTargetmanifest (registry.aethercert.com/v2) you copied from somewhere else - for example one an AI assistant wrote, or one you exported from target discovery.
Imported and pasted manifests open in the JSON editor. A manifest can be up to 256 KiB. The check runs on the server as you type, and Save draft keeps your work even while the manifest still has errors. Once the manifest passes the schema check, Continue in form opens it in the form editor, and Edit as JSON goes back. Releasing always happens from the form's Review & publish step, with the same checks as every other target.
What the check stages mean
The check runs four stages in order. A stage runs only when the stages before it passed; otherwise it is shown as skipped, so one mistake is not reported twice.
| Stage | What it checks | What you see |
|---|---|---|
| Parsing | That the text is one valid JSON object, within the size limit. | The line and column of a syntax error. A key that appears twice in one object is a warning: JSON keeps only the last value. |
| Schema | The structure: required fields, unknown fields, types, allowed values. | Every structural problem at once, each with the path of the field, for example operations.bind.rest.method. |
| Semantic | The rules between fields: references to declared parameters and state, executors and their payloads, workflows, conditions. | The first problem found, with its path. |
| Security | Secrets, key material, permissions, trust levels, literal hosts and paths, PowerShell scripts. | The first problem found, with its path. |
The semantic and security stages stop at the first problem, exactly like the agent does.
When one of them fails, the other is shown as skipped; fix the problem and check again.
Each issue carries a code, such as SCHEMA_UNKNOWN_FIELD or PERMISSION_MISSING, that
names the kind of problem.
One rule is softer while you work: a permission that no operation needs is a warning in a draft. It is still refused when you release, because a package may declare exactly the permissions its operations need - no less and no more.
Next to the issues, the security summary lists what the target would be allowed to do: how it runs, which hosts it connects to, whether it receives the private key, which files it writes, whether it controls a service or runs PowerShell scripts, and any text that looks like a hard-coded password or token. The summary is informational: it helps whoever releases the target, and it never decides whether the manifest is valid. It appears once the manifest passes the semantic and security stages.
Draft provenance
Every draft shows where it came from, in the In progress list and in the editor header, for example Source: AI generated · Status: Draft.
| Badge | Meaning |
|---|---|
| Manual | Built in the form editor. |
| Imported | Imported from a file or pasted as JSON. |
| AI generated | You declared that an AI wrote it, or an AI assistant created it over MCP. |
aethercert sets the source when the draft is first saved, and it never changes after that. Editing an AI-generated draft in the form keeps it AI-generated. When you paste or import a manifest, tick This manifest was generated by an AI if that is the case, and optionally name the AI provider. You can mark a draft as AI-generated, but nothing can mark an AI-generated or imported draft as manual.
Imported and AI-generated drafts show a notice in the review step. Before you release one, check what each operation does and what it may access - the security summary lists it. The released version keeps a record of how it was authored and who released it.
Connecting an AI assistant over MCP
An AI assistant that supports the Model Context Protocol (MCP) can work with the Target Registry for you: read the schema and the vocabulary, look at existing targets as examples, check a manifest it wrote, and save it as a new draft for you to review.
Endpoint: https://api.aethercert.com/api/mcp
Add this URL as a remote MCP server in your assistant. The assistant must support MCP authorization with OAuth and Client ID Metadata Documents; an assistant that only supports dynamic client registration, or that runs as a web page in your browser, cannot connect.
Allowing the connection
The first time the assistant connects, it opens the aethercert dashboard in your browser:
- Sign in with your second factor (or a passkey). If you normally use an MSP portal domain, sign in on the dashboard address the assistant opens.
- Choose an organization. The assistant works in exactly the organization you choose, and only in that one.
- Review and allow. The consent page shows the assistant's name - which is the assistant's own claim - and the domain that identifies it. aethercert does not verify who runs that domain, so allow it only if you trust it. Then choose Allow or Deny.
The assistant can ask for these permissions:
| Permission | What it allows |
|---|---|
| Read the Target Registry | Read the schema and the vocabulary, search and read the targets you can see, and check manifests. |
| Create drafts | Additionally save a manifest as a new draft in the chosen organization, marked AI-generated. Needs the admin or owner role there. If you do not have it, only read access is granted. |
| Stay connected | Keep working without asking you again, for up to 30 days. |
An AI assistant can never release a target
The assistant can only create new drafts. It cannot change or discard an existing draft, and it can never release, publish, install or configure a target. Every draft it creates is marked AI generated and waits in In progress until a person in your organization reviews it and releases it - or discards it. Treat its manifest like code from an unknown author: check the operations and permissions before you release.
The assistant gets a link to each draft it creates. A draft it creates for a package that already has a draft is refused, so it never overwrites work in progress. Your organization can receive at most 20 drafts per hour this way.
How long a connection lasts
A connection ends by itself after 7 days without use, and after 30 days at the latest. The assistant then asks you to allow it again. If you are removed from the organization, the connection stops working at once.
Revoking a connection
Settings > Connected apps lists every assistant you connected, with its organization, its permissions and when it was last used. Revoke ends a connection immediately: the assistant's next request is refused.
Signing out everywhere, signing out your other devices, and resetting your password also disconnect every connected assistant.