Data and security

Getting your data out

Any backlog can be downloaded as a complete, loss-free copy from inside the app at any time — items, sub-items, notes, tags and the full history of who changed what. The file is plain, documented JSON with a tamper-evident signature, and it can be restored back into the app.

An organisation can pull all of its content programmatically, on a schedule, authenticated by its own corporate directory. There is no API key to create or look after: access is granted and revoked in your directory, alongside your joiners-and-leavers process.

A nightly export, ready to schedule
#!/bin/sh
# Nightly: pull everything out into a dated file that you keep.
# The token comes from YOUR directory (client credentials); the service
# issues no API key and stores no credential for this.
# set -eu and the -f/-e flags make any failure — bad credentials, an
# outage, no token — stop the script with an error, so it can never
# write something that merely looks like a backup.
set -eu
TOKEN=$(curl -fsS -X POST \
  "https://login.microsoftonline.com/<your-directory-id>/oauth2/v2.0/token" \
  -d grant_type=client_credentials \
  -d client_id="<your-automation-app-id>" \
  -d client_secret="$AUTOMATION_SECRET" \
  -d scope="api://<sign-in-client-id>/.default" | jq -re .access_token)

curl -fsS -H "Authorization: Bearer $TOKEN" \
  "https://<this-site>/api/tenant/export?tenant=<your-company-id>" \
  -o "backlog-export-$(date +%Y-%m-%d).obk.json"
Converting an export into spreadsheets
// node export-to-csv.mjs backlog-export-2026-01-31.obk.json
// Turns an export into one .csv per backlog — readable in Excel or
// anything else, with no software of ours involved.
import { readFileSync, writeFileSync } from 'node:fs';

const file = JSON.parse(readFileSync(process.argv[2], 'utf8'));
// A cell that starts like a formula gets a leading apostrophe, so a
// spreadsheet shows it as text rather than evaluating it.
const cell = (v) => {
  const s = String(v ?? '');
  return '"' + (/^[=+@-]/.test(s) ? "'" + s : s).replaceAll('"', '""') + '"';
};
let n = 0;
for (const backlog of file.payload.backlogs) {
  const rows = [['Ref', 'Parent', 'Description', 'Status', 'Size', 'Tags', 'Notes']];
  const walk = (items, parent) => {
    for (const item of items ?? []) {
      rows.push([
        item.ref ?? item.id, parent, item.description, item.status,
        item.size ?? '', (item.tags ?? []).join(' '),
        (item.notes ?? []).map((note) => note.text).join(' | '),
      ]);
      walk(item.children, item.ref ?? item.id);
    }
  };
  walk(backlog.items, '');
  const name = backlog.name.replace(/[^A-Za-z0-9 _-]/g, '').trim() || 'backlog';
  n += 1; // numbered: two backlogs may share a name, and nothing may overwrite
  writeFileSync(n + ' ' + name + '.csv', rows.map((r) => r.map(cell).join(',')).join('\n'));
}

The second script uses no software of ours, so a copy you have downloaded stays readable whatever happens to this service.

Administrators find the same export as a button, with the exact commands for their own directory, on the company page.

Automated review of the code

Every release is reviewed automatically by a language model that is not part of the team writing the code, and the result is published here with the date it ran, the change it covers, and the exact instructions the reviewer was given. The review re-runs on each deployment, so an old date means the running code has not changed since. What is published is deliberately coarse — an assessment per area, the outcome of each check on a fixed list drawn from the OWASP Top Ten, and counts of open findings by severity — and carries no code, file names or other internals.

The instructions the reviewer is given

For each area: You are an independent security reviewer producing a PUBLIC assessment of one area of a codebase for prospective customers. You did not write this code and owe its authors nothing: be fair, not kind — report what the code actually shows, neither softened nor inflated, and credit protections that are genuinely present. You assess the area against a fixed checklist drawn from the OWASP Top Ten, and every finding names its check: "access-control" — authorisation that is missing or bypassable, or data crossing organisation boundaries; "crypto" — weak or misused cryptography, secrets handled or stored badly; "injection" — injection of any kind, including cross-site scripting; "config" — insecure defaults, headers or deployment configuration; "components" — vulnerable, outdated or unnecessary dependencies; "auth" — flaws in sign-in, session handling or credential lifecycle; "integrity" — unverified updates, unsafe deserialisation, or supply-chain weakness in the pipeline; "logging" — security events that would go unrecorded or unnoticed; "ssrf" — requests the server can be tricked into making; "other" — any real problem outside these categories, stability included. Weigh every finding by risk — how likely it is to be exploited and what happens if it is. "critical" means attackers could plausibly compromise data or accounts today; "high" means a serious weakness to fix promptly; "medium" means a real weakness of limited impact or needing unusual circumstances; "low" means a worthwhile hardening. Do not inflate a theoretical concern to signal diligence, and do not omit a problem because the rest of the area is good. You answer with STRICT JSON only, of the shape {"confidence":"high"|"medium"|"low","note":string,"findings":[{"severity":"critical"|"high"|"medium"|"low","check":string,"note":string}]}, where "check" is one of the checklist ids above. "confidence" is how confident a customer should feel about this area. Each note is plain prose for a non-technical reader, at most 350 characters. Because the assessment is public, notes must NEVER contain code, secrets, file names, paths, URLs, function or variable names, or step-by-step exploit detail. List at most 5 findings, only for problems that matter; style preferences are not findings. An empty findings list is a valid answer.

For the overall verdict: You are an independent security reviewer summarising a completed review for prospective customers. Answer with STRICT JSON only: {"verdict":string} — one plain-prose paragraph, at most 700 characters, honest about weaknesses, no code, names, paths or URLs.

Reviewed 25 August 2026, 14:35 UTC (29 days ago) · change 10aad32 · 98 files · model @cf/meta/llama-4-scout-17b-16e-instruct

Every area is assessed against a fixed checklist drawn from the OWASP Top Ten. What was checked, and how many findings each check left open:

Checked forCriticalHighMediumLow
Broken access control0020
Cryptographic failures0001
Injection and cross-site scripting0010
Security misconfiguration0055
Vulnerable or outdated components00110
Authentication and session failures0062
Software and data integrity failures0012
Security logging and monitoring failures00010
Server-side request forgery0000
Other risks0000

The reviewed system demonstrates a strong security posture, with robust access control, authentication, and authorization mechanisms in place. However, several areas require attention, including session management, data storage, and logging. Some components are outdated or use fixed versions, which may pose security risks if not regularly updated. Additionally, a few potential issues were identified, such as the use of a personal account as a recovery holder and the lack of explicit access control checks for certain operations. Overall, the system appears to be secure, but further improvements are necessary to address these concerns and ensure the security of user data.

Open findings for the team to look at: 0 critical, 0 high, 16 medium, 30 low.

What is built in

The overview at Security covers the same ground in the terms a security reviewer will ask about.

All policies · Sign in