Dispatch · Trust

What we hold, and what protects it

Written for the person filling in a security questionnaire. It is generated from the code's own retention rules, so it cannot quietly drift from what the software actually does.

Not ready to publish. Bracketed items still need this deployment's real details, and no part of this has been reviewed by a lawyer.

Sub-processors

Everything that processes customer data. Your own client can object to any of these, so the list is complete rather than convenient. We give 30 days' notice before adding one.

WhoWhat forWhereWhat they can see
LinkedIn (Microsoft)publishing, and the analytics read backglobalthe posts you publish and the pages you connect
[hosting provider]runs the application and the database[region]everything, encrypted at rest
[mail provider]invitations and notifications[region]recipient addresses and message contents
[model provider]drafting and research, where you use it[region]the briefs and drafts you send it, never LinkedIn member data

How long anything is kept

These are the values the code enforces, not a policy written beside it. Deletion runs on a schedule; /api/retention shows whether anything is overdue, and it is readable by any signed-in customer.

WhatKeptWhy that long
li_actors1 daysother members' profile data — cache only
resets1 dayspassword reset links — a way into an account, held for hours and deleted within a day
li_member_activity2 daysmember social activity
li_comments6 weeksorganization social activity
li_mentions6 weeksorganization social activity
li_org_profile8 weeksorganization profile data, authenticated
li_deliveries2 monthswebhook de-duplication, our own
li_stats1 yearpage admin and reporting data
li_member_stats1 yearthe authenticated member's own data
enquiries2 yearsthe client's own enquirers, in their own words — their commercial record, kept two years so a year-on-year comparison is possible, then gone
voice_vetoes2 yearsa person saying a draft did not sound like them, with their name. Two years: after that the record it fed into is the thing that matters, not the objection
sign_offs7 yearswho approved what, with the address it came from. Seven years, because the question an approval answers is asked long after the fact and a regulated client's retention obligation is usually six
claimswhich figure in which post rests on which source. Ours, about our own posts, and the thing the report cites.
expectationswhat was agreed with a client and when. A name is stored because 'agreed with somebody' answers nothing, and it is deleted with the account.
li_cursorour own bookkeeping — where each pull got to. No LinkedIn data: timestamps and URNs we already hold, and a URN may be kept without limit.
li_hooksour own webhook registrations: an organization URN, an event name and our callback URL. A URN may be kept without limit, and a registration that expired silently is deleted when the destination is disconnected, not on a clock.
post_versionsevery version of our own copy, with who changed it. Our work product, and the answer to what a post said when it was approved.
proposalswhat we recommended and what the client decided. The record that answers 'you never brought us ideas'.
sourcesa web address, a publisher, a date and a sentence quoted from a public page. No personal data, and deleting it would break the citation on a post that is still live.
voice_recordshow a brand argues, what it refuses to say, what is off limits. Configuration, written by the account itself.

Two consequences worth stating. A comment and the person who wrote it have different clocks — the comment is organization activity at six weeks, the commenter's name is another member's profile data at twenty-four hours — so after a day a comment is still there and its author reads as "A LinkedIn member". And LinkedIn's terms do not permit member data to leave the application, including to you: client reports are built from aggregates, and the export path refuses to render a structure containing a name.

Measures actually in place

Each of these is something the test suite exercises, not an intention.

LinkedIn tokens encrypted at rest

Sealed before they reach the database and authenticated on read, so a tampered row fails loudly rather than decrypting to nonsense. A stolen copy of the database is not a stolen set of LinkedIn accounts.

Passwords hashed with scrypt

Salted per user, n=2^14. Not recoverable by us. A wrong password and a missing account take the same time, so neither can be told from the other.

Account isolation enforced in one place

Every account's reach is computed by a single function and every route asks it. The test suite enumerates every route the application exposes and attacks each one with an identity that must not reach it — a route added later without a check fails without anyone remembering to test it.

Refusals never confirm what exists

An account you may not see and an account that does not exist return the same status and the same words.

Append-only audit log

Nothing in the system updates or deletes an audit row. Who approved, connected, changed or erased what, and from which address.

Sign-in throttled two ways

On the address and on the network address separately, so one attacker cannot lock every account out and a botnet cannot walk through.

Cross-site request forgery closed twice

A session cookie that is HttpOnly and SameSite=Lax, and an origin check on every state-changing request.

Deletion on a schedule, not on read

A row filtered out of a query is still a row in the file. The retention sweep deletes, and /api/retention shows whether anything is overdue.

Record of processing (Article 30)

As a processor to you, and a sub-processor where you are acting for your own client.

Categories of data subjectStaff of the agency; staff of the agency's client brands; LinkedIn members who comment on or mention a published post
Categories of personal dataName, business email address, role, hashed password, last sign-in; authored post content; LinkedIn access tokens; for commenters, the name, headline and photograph LinkedIn returns
Special category dataNone. Do not put any into a post.
PurposeScheduling and publishing content to LinkedIn on the controller's documented instruction, and reporting on it
RecipientsLinkedIn; the sub-processors listed above; nobody else
Transfers[mechanism — SCCs Module 2 plus a transfer impact assessment]
RetentionAs set out in the table above. Erasure is a button and it deletes, including files on disk
SecurityAs set out below

What we do not have

A trust page that only lists strengths is a trust page nobody believes. These are the gaps, and when each would be worth closing.

No SOC 2, no ISO 27001, no Cyber Essentials — yet

None is held today. For UK and EU buyers Cyber Essentials Plus is the usual ask and is days rather than months; it is the one we would pursue first, at around ten customers. SOC 2 Type II is 12–18 months end to end and worth starting only when a named deal depends on it.

No uptime SLA

There is no measured operating history to commit against, and a service credit is cheap while a broken promise is not. This will be offered once there is a quarter of real numbers behind it.

No penetration test

Not yet commissioned. The isolation suite is adversarial and mutation-tested, which is not the same thing and is not offered as if it were.

Never tested against the live LinkedIn API

Everything is written from LinkedIn's documentation and proven against a test double. The Standard tier application has not yet been made.

Cookies

One, called session. It is what keeps you signed in: HttpOnly, SameSite=Lax, twelve hours. There are no analytics or advertising cookies and no third-party trackers, which is why there is no cookie banner.

If something goes wrong

We will tell affected accounts and, where required, the supervisory authority within 24 hours of becoming aware — tighter than the 72 hours a controller owes a regulator, because you need time to make your own notification. We will say what we know even where that is not yet everything.

Asking us something

Security questionnaires: send CAIQ Lite or SIG Lite to [security contact] and we will return it within five working days. Data protection: [privacy contact]. The data processing addendum is at /dpa.

What this product generates

Assembled with the help of a language model. Check each figure against the source shown beside it before acting on it.