CLI › profiles
profiles
A profile is an array of up to twenty objects with nine possible fields each,
which is more structure than a flag naturally carries. profiles create takes
it three ways, and they exist for three different callers.
profiles create --require, for a one-liner
curl -s -X POST https://api.propgate.dev/v1/profiles \
-H "authorization: Bearer pg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H 'content-type: application/json' -d '{
"key": "sending",
"requirements": [
{ "key": "ns", "check": "delegation" },
{ "key": "spf", "check": "spf", "include": "_spf.google.com" },
{
"key": "dkim",
"check": "dkim",
"selector": "google",
"requiredPerDomain": ["expectedPublicKey"]
},
{ "key": "dmarc", "check": "dmarc" },
{ "key": "mail", "check": "mx", "expectsMail": true }
]
}'Created sending.
sending version 1
ns delegation
spf spf include=_spf.google.com
dkim dkim selector=google, per domain: expectedPublicKey
dmarc dmarc
mail mx expectsMail=trueEach --require is <key>:<check>[:field=value,field=value], repeatable up
to the twenty the API allows.
The field names are the API's own body field names, verbatim. Not
--dkim-selector but selector; not --spf-include but include. That is
deliberate: when the server refuses a definition it names the field, and an
alias here would mean the error and the input never quite match.
| Check | Fields |
|---|---|
delegation | none |
spf | include |
dkim | selector (required), expectedPublicKey |
dmarc | none |
mx | expectsMail |
caa | caaIssuer (required) |
Every check also takes requiredPerDomain, naming a field each domain
supplies rather than this profile. A DKIM key is issued per domain, so that is
almost always where it belongs:
--require 'dkim:dkim:selector=google,requiredPerDomain=expectedPublicKey'Repeat the assignment to name more than one — requiredPerDomain=selector,requiredPerDomain=expectedPublicKey
— because a comma already separates fields within a --require, and a second
separator to learn is worse than repeating the word. Which names are legal is the
server's to say. Supplying the values is
domains add --expect.
Values keep everything after the first =, so a base64 key retains its
padding — a DKIM key that quietly lost its == is one that never matches for
a reason nobody can see.
What is checked here, and what is not
Two rules are enforced before anything is sent: dkim needs a selector
and caa needs an issuer — from this profile, or from every domain via
requiredPerDomain. Deferring one still keeps the promise, just somewhere else:
registration refuses a domain that supplies no value for it.
$ propgate profiles create --key sending --require 'k1:dkim'
propgate: k1: dkim needs a selector, as k1:dkim:selector=<name>, or requiredPerDomain=selectorThose two are not a second copy of the server's validation — they are the two
that decide which question the guided flow asks next, so this code needs them
anyway. Everything else about a valid profile stays on the server: duplicate
keys, more than twenty requirements, two of a kind that may only appear once,
and which field names requiredPerDomain may hold. A second implementation of a
rule is a second thing that can disagree, and the API's 422 is already the
better message.
profiles create --file, for something generated
propgate profiles create --file profile.json
# or from a generator, over stdin
your-generator | propgate profiles create --file -Takes the POST /v1/profiles body exactly — { "key": …, "requirements": […] }
— and - reads stdin. It carries the key too, so it is refused alongside
--key and --require rather than leaving a reader to guess which wins.
No flags at all, for a person
$ propgate profiles create
│ What should this profile be called?
│ sending
│
│ Name this requirement
│ dkim
│
│ What should "dkim" check?
│ ○ delegation ○ spf ● dkim ○ dmarc ○ mx ○ caa
│
│ Which DKIM selector?
│ google
│
│ Is the public key different for every domain?
│ ● Yes / ○ No
│
│ Add another requirement?
│ ● No / ○ YesOne requirement at a time, asking only the fields that check actually has.
mx offers three answers rather than a yes/no, because expectsMail is
tri-state: unstated makes no claim, and false asserts the domain receives no
mail — which makes a null MX correct rather than a fault.
dkim asks whether the public key differs for every domain, and defaults to
yes. A profile holding one literal key is a profile that works for exactly one
domain; someone reaching this prompt with ten thousand of them needs the default
to be the shape that scales, and the other answer is one keypress away. Answering
yes sets requiredPerDomain and skips the question about the key itself, because
there is no single key to ask for.
profiles get
propgate profiles get sendingReturns the current version — the one a new registration against this key would pin to. Domains already registered keep their own version regardless. See Profiles and versions.