Legal & Privacy: Deploying TIER Where Per-Developer Measurement Is Regulated
Evaluation mode (operator choice)
Team reports are name-free and need at least k people (default 5, minimum 3). An operator can turn on evaluation mode to see small rows themselves while setting up; shared viewers never see them. This operator choice amends #185. k guards against accidental disclosure to viewers; it does not stop an admin inventing names. See Privacy for setup, the viewer rule, labels, and the prohibition on sealing small rows. Turn evaluation mode off and set k_anonymity to 3 or more (default 5) to share team reports. While k is below 3, shared viewers see team rows of 3 or more people.
v0.7.0 organizations: Use the credential scope map for current administration and report access. This guide remains separate from the data inventory and trust limits.
⚠️ This document is not legal advice. It is deployment and positioning guidance written by engineers, not lawyers. Employment law, works-council obligations, and data-protection rules vary by country, by industry, and over time, and they turn on facts specific to your organization. Before deploying TIER in a way that measures named individuals, consult your own legal counsel, your Data Protection Officer (DPO), and — where one exists — your works council or employee representative body. Nothing here creates a compliance guarantee.
Why this document exists
TIER attributes AI token spend to outcomes. In v0.7.0, named coaching cards
are available on real data with serve --aggregation developer when a nonempty
admin API token, a nonblank --admin-viewer operator identifier and at least
one active permitted viewer credential are configured. This may be a legacy
subject-bound viewer credential or an eligible personal/node key for a current,
mapped person. Each card also requires
positive verified spend in its window and either a configured subject viewer
credential or a live declared-viewer check, under the
declaration and view-log rules.
Declared-viewer card opens require a writable server; every card open must
commit its view log before the card is built.
TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual.
In several of TIER's target markets, measuring the performance of
named employees is legally constrained — sometimes requiring prior
co-determination or works-council
agreement, sometimes restricted outright under data-protection law. Adopters
need to understand that exposure before their legal and HR review, not after.
This guide covers: what TIER actually measures and stores; the EU labor-law exposure of per-developer measurement; TIER's posture under GDPR Article 22 (automated profiling); when a Data Protection Impact Assessment (DPIA) is indicated; the works-council consultation prerequisites; and a jurisdiction-by-jurisdiction decision table for choosing a deployment mode.
TIER's stance, in writing
TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual. TIER sets weighted merged work beside captured AI usage for coaching conversations; its positioning is grade the work, not the worker, by policy rather than by mechanism. Team reporting and access controls reduce disclosure but do not validate individual figures.
Two independent reasons make this the right posture:
- Legal. In co-determined jurisdictions (below), using a measurement system as an input to individual appraisal is precisely the use that triggers the heaviest obligations, and can be unlawful without prior agreement.
- Methodological. Per-developer TIER is easily distorted — by task mix, pairing, seniority, review load, and the incentive to game any number that is tied to a person's evaluation. TIER measures spend efficiency of a body of work, which is a team-and-portfolio property, not a fair proxy for individual worth.
The per-developer view is for coaching (a developer and their manager looking at how that person works with AI) and for engineering diagnosis (for example, "which spend is missing an issue reference?"). Make organizational decisions from team-level numbers.
What developer mode is (v0.7.0). It is a coaching view that a developer
and their permitted viewers read together, seeing the same numbers. A tool that
shows named people's numbers can be used to monitor individual performance,
whatever you intend, so the rest of this document applies to it in full.
TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual.
TIER cannot enforce that stance. It shows numbers; it cannot stop someone from copying one
into a review. Only your written policy, or a works agreement where one
applies, can.
Access and retention controls. Developer mode on real data requires a
nonempty operator API token, a named audited operator and at least one active
permitted viewer credential. The developer, their declared manager, optional skip-level
manager and declared works-council viewers can receive separate credentials.
Shared read credentials cannot read named pages. Views are logged and the subject
can inspect that log on My card with a personal sign-in. In team or division
mode with evaluation off, a write-token export is not logged. The legacy
DELETE /api/v1/developer/{id} writes no audit row; the root
DELETE /api/v1/org/people/{dev} writes a name-free person_erased audit row.
The developer list has no TIER order. Use the
credential scope map
for who creates people, issues keys and reads reports. It links the separate
rules for branch administration, personal-key custody and declared card access.
The evaluation-mode choice
includes the legacy shared admin token's access and audit label. These API
controls do not restrict a host owner who can read the database file.
In real writable developer mode, named usage and outcomes are pruned at startup and daily: 90 days by default, 60–365 days configurable. Name-free historical totals remain in roll-ups. A permanent watermark refuses older named writes; widening the window works forward only and cannot restore pruned history. Switching to team or division mode continues an already-armed retention policy. Team or division mode that has never armed that policy does not prune named usage and outcomes. Org audit names age out in every real writable mode. View logs have their own retention policy. Restrict access to the local database as well as the API.
What TIER measures and stores (and what it never touches)
The single most important fact for a privacy review: TIER never stores
prompt or completion content, source code, or file contents, outside the free
text of raw GitHub webhook payloads (below), and never sends any of it
anywhere you have not already sent it: the optional reverse proxy passes
prompts on to the provider you chose. Its parsers are field allowlists — token counts and metadata only.
One opt-in switch, worktree attribution (off by default), widens the read when
turned on, to find which branch the work was on. It decodes the file paths
(file_path, notebook_path, path) from every tool call in every session
file it scans, including sessions in repositories you did not configure, which
are then dropped with nothing stored; it reads a git reflog, whose lines carry
the committer's name and email and, for a commit, its subject line, only for a
linked worktree of a repository you configured that those paths or the
session's own folder are in, and for any other project it reads only the .git
pointer and worktree admin files, never its reflog. It never reads the files the
paths name, keeps none of those reflog fields and stores no path in an event,
but the live watcher's checkpoint row keeps the absolute path of the worktree it
is carrying, and spend in another repository's worktree is stored as
unattributed:foreign-repo, without that repository's name or path; the full
list is in privacy.md.
Parents no longer carry (#1016); only message groups labelled isSidechain:true can use carry. Worktree attribution stays opt-in and off by default. Activation requires recorded gates, the operator's security rulings and an explicit operator decision. No new accuracy figures have been measured.
Full, code-grounded detail is in docs/privacy.md (guarantee verified against the code on 2026-07-04). In summary, TIER stores in a single local SQLite file, with no external transmission by default:
- a developer identifier (an OS username, or a GitHub login for PR outcomes) plus any alias mapping you configure;
- an issue id derived from a branch name or PR/commit body;
- model names, token counts, and list-price cost in micro-dollars;
- PR metadata (number, author login, size-derived weight, quality, merge SHA); and
- two conditional stores that hold personal data and that an auditor should
note specifically: watcher tail-state (only in live
--watch-repomode) and raw GitHub webhook payloads (only when the webhook path is enabled). The raw webhook payloads do contain contributor names, email addresses, PR titles, and commit messages (the same PR/commit metadata GitHub itself stores); that text is kept as written, including anything pasted into it. They are bounded to roughly 90 days; the per-developer erasure route does not reach them, and editing the text on GitHub does not remove TIER's copy. See docs/privacy.md for the exact fields, retention bounds, and how to store none of it (run without the webhook path).
The privacy guarantee bounds content. It does not by itself resolve the labor-law question, because the developer identifier plus cost attribution is personal data about a named individual regardless of whether any prompt text is stored. That is the subject of the rest of this document.
Organization access and separate installations
A v0.7.0 organization tree scopes delegated API access within one installation.
It does not turn that installation into a service for mutually untrusted tenants.
TIER remains single-tenant with no cross-team/cross-entity data isolation:
every org table uses tenant_id='', and developer identifiers remain global
within the database. Root administration and host access remain trust boundaries;
a node key's branch limit does not constrain the host owner.
- Do not run TIER as a shared multi-org service. Run one instance per team or per organization. TIER cannot enforce data segregation between cohorts, business units, or legal entities within a single database — that separation must be achieved by running separate instances with separate database files and separate access control.
- Do not represent to a works council or DPA that TIER provides
cross-team/cross-entity data isolation. It does not. A v0.7.0 node key's branch
limit is delegated API access within one installation, not data isolation.
Separate processes and their local SQLite files (mode
0600) remain the installation boundary.
For a deployment review, record the people and key inventory boundary, including subtree padding, the one server per developer rule, and the federation acceptance limit. Separate database files and host access controls are still needed when separate installations are the intended boundary. Include the child upstream SSRF residual in the deployment's network review. For a transfer between installations, the graft snapshot boundary states what remains at the receiving server after source erasure or consent withdrawal.
EU labor-law exposure of per-developer measurement
In much of the EU, systems that monitor employee performance or behavior are subject to co-determination or works-council consultation before they may be introduced. Per-developer TIER, which shows an efficiency number for each named developer, is squarely the kind of system these rules govern. The threshold is generally the capability to monitor individual performance, not whether you subjectively intend to use it that way.
Germany — Betriebsrat co-determination (§87 BetrVG)
Under §87(1) No. 6 of the Betriebsverfassungsgesetz (BetrVG), the works council (Betriebsrat) has a mandatory co-determination right over the introduction and use of "technical devices designed to monitor the behavior or performance of employees." German case law reads this broadly: a system that is objectively suitable for monitoring individual performance is covered even if that is not its stated purpose. A per-developer TIER deployment is very likely in scope.
- Consequence: where a Betriebsrat exists, introducing per-developer TIER generally requires a works agreement (Betriebsvereinbarung) negotiated in advance. Deploying without one can render the measurement unlawful and its outputs unusable, and can expose the employer to injunctive relief.
- Team-only aggregate reporting that never surfaces individual performance substantially reduces (though a works council may still wish to be consulted about) this exposure.
France — CSE works-council consultation
In France, introducing a tool capable of monitoring employee activity generally requires prior information-and-consultation of the CSE (Comité Social et Économique) (see, broadly, Art. L2312-38 of the Code du travail), and employees must be informed in advance of any system used to monitor their activity. The CNIL (the French DPA) has repeatedly emphasized proportionality and transparency for workplace monitoring. Per-developer measurement without prior CSE consultation and employee information is a live legal risk.
Netherlands — works council consent (WOR Art. 27)
Under the Wet op de ondernemingsraden (WOR), the works council (Ondernemingsraad) has a consent right (instemmingsrecht) under Article 27 over decisions to adopt, amend, or withdraw arrangements for personnel monitoring or for processing personal data of employees, including systems that monitor presence, behavior, or performance. Adopting per-developer TIER without the OR's prior consent can make the introduction voidable.
Other EU/EEA jurisdictions
Most EU/EEA member states have an analogous works-council consultation or co-determination regime for employee-monitoring systems (e.g. Italy's Art. 4 of the Statuto dei Lavoratori, which restricts remote monitoring of workers). Assume consultation is required and confirm locally. The safe default in any EU/EEA jurisdiction is team-only aggregate reporting plus advance consultation.
GDPR Article 22 posture (automated profiling)
GDPR Article 22 restricts decisions "based solely on automated processing, including profiling," that produce legal effects or similarly significantly affect an individual. TIER's designed posture keeps it clear of Article 22:
- TIER does not make decisions. It produces a number for coaching and diagnosis. It does not automatically discipline, rank-and-yank, deny promotion, or alter compensation.
- Keep a human in the loop and keep TIER out of appraisal. Article 22's strongest protections attach when an automated output solely drives a significant decision about a person. TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual. The coaching stance does not itself establish a deployment's legal classification. If an adopter does wire TIER outputs into individual HR decisions, they change the legal analysis and likely trigger Article 22 (and the co-determination regimes above) in full.
Independently of Article 22, per-developer cost attribution is personal data under GDPR. The usual obligations apply: a lawful basis (legitimate interest will require a balancing test and is weakened by any appraisal use), transparency to the data subjects, data minimization, purpose limitation, and storage limitation. Team-only aggregate reporting that cannot single out an individual is the strongest data-minimization posture.
When a DPIA is indicated
A Data Protection Impact Assessment is required under GDPR Article 35 when processing is "likely to result in a high risk" to individuals — explicitly including "systematic and extensive evaluation of personal aspects ... based on automated processing, including profiling" and "systematic monitoring." Several EU DPAs list employee monitoring on their mandatory-DPIA lists.
Practical guidance:
- Per-developer deployment: treat a DPIA as expected. Systematic evaluation of employees' work efficiency is a textbook high-risk case.
- Team-only aggregate deployment: a DPIA is far less likely to be required, because processing that cannot single out an individual is not "evaluation of personal aspects" of a data subject — but document that reasoning and confirm with your DPO.
- Do the DPIA before deployment, involve the DPO, and where consultation is required, sequence it with the works-council process (below). A DPIA is also the natural place to record the retention bounds and the conditional personal-data stores documented in docs/privacy.md.
Works-council consultation prerequisites (checklist)
v0.7.0 availability: In developer mode, named coaching cards are available on real data to permitted viewers and the audited operator; the per-issue report remains denied in real-data developer mode. tierd demo shows its own invented data read-only in a private temporary database and cannot load yours (code: internal/api/identity.go, identityRoutePolicies, identityBoundary; internal/api/coaching.go, handleCoaching; cmd/tierd/demo.go, runDemo).
Where a works council or equivalent body exists, treat the following as prerequisites before per-developer TIER goes live. Adapt to local law with counsel:
- Engage early. Bring the works council in at the design/decision stage, not after deployment. In Germany the co-determination right precedes introduction.
- Limit the purpose in writing. TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual. State the coaching purpose, what is measured, and the methodological limits.
- Describe the data. Provide the docs/privacy.md field list: what is stored, the no-content guarantee, retention bounds, and the conditional PII stores (watcher state, raw webhook payloads).
- Prefer the least-intrusive mode. Offer team-only aggregate reporting as the default; justify any per-developer processing against necessity and proportionality.
- Agree who may view, how views are logged, and how long data is kept. Name who may see a developer's numbers (for example, the developer and their declared manager); agree an audit log of who viewed what; set a retention period; and say how the single-tenant local database is protected. Per-viewer credentials, view logging and bounded retention are built; the agreement must specify their configuration and who administers them.
- Reach the required instrument — a Betriebsvereinbarung (DE), CSE information-and-consultation record (FR), or OR consent (NL) — before go-live.
- Provide transparency to employees and a route to raise concerns.
- Complete the DPIA and reconcile it with the consultation outcome.
Deployment decision table: team-only vs per-developer, by jurisdiction
The recommended deployment mode depends on where your developers are employed (the location of the employees measured, not the company HQ). "Team-only" here means reporting that never surfaces an individual developer's performance.
Availability note (accurate as of 2026-10-22): TIER now ships a dedicated team-only aggregation mode with a k-anonymity floor (issue #185). It is selected by a REQUIRED
--aggregation team|divisionsetting ontierd serve(envTIER_AGGREGATION, config keyaggregation): there is no silent default.developerrequires subject-bound credentials and a named audited operator on real data.tierd serverefuses to start until you choose, so an existing deployment can never change its reporting posture on upgrade by accident. InteamordivisionmodeGET /api/v1/scores, the dashboard, andGET /api/v1/scores/{developer}never return an individual developer name: named rows are replaced by team aggregates, and any team with fewer than the k-anonymity floor of counted people is collapsed into an aggregate "other" bucket. Since #856 an identifier counts only if it is on the roster, is not a bot, and has activity a collector, the proxy or a pull request captured in the window (not only hand-entered/costsspend or push-only merged work); each published figure (cost, points, paid spend, and each part of thecoverage_pctsplit) also needs k counted people behind it. This protects what a read-token holder sees; the write token can edit the roster and aliases and is an admin credential until #908 (manager-faq.md has the full rule and the remedy). These modes publish one breakdown of each window (#864): the group rows and the grand total, with no work-type, per-model or cost-category split beside them, because two breakdowns subtract to a group below the floor. ⚠️ A residual that is itself below the floor withholds the whole response (#593, #864), the named rows and the grand total included, and says so indata_quality.kanon_suppressed. When the residual clears the floor it is emitted and its people's spend and outcomes remain in the totals. The floor defaults to k = 5 with a hard minimum of 3 (--k-anonymity, envTIER_K_ANONYMITY, config keyk_anonymity); without evaluation mode,tierd serverefuses to start with a smaller value. The localtierd scoreCLI is a deliberate carve-out — it is a single-operator tool that reads the invoking user's own JSONL, not a served multi-viewer surface, so it is not gated. Still restrict access and consult as required: team mode removes individual rows from shared reports, but the underlying database still stores per-developer identifiers (see the storage note below), so run one instance per cohort and follow the works-council / DPIA steps below.
| Jurisdiction of measured employees | Recommended mode | Prerequisites before go-live | Rationale |
|---|---|---|---|
| Germany (DE) | Team-only | Betriebsrat co-determination; works agreement (§87 BetrVG) if any individual-level capability remains; DPIA | Per-developer monitoring is co-determined under §87(1) No. 6; suitability to monitor is enough to trigger it. |
| France (FR) | Team-only | Prior CSE information-and-consultation; advance employee notice; DPIA | Monitoring tools require CSE consultation and transparency (Code du travail L2312-38; CNIL guidance). |
| Netherlands (NL) | Team-only | OR consent under WOR Art. 27; DPIA | Personnel-monitoring arrangements need works-council consent before adoption. |
| Other EU / EEA | Team-only (default) | Local works-council consultation; DPIA; lawful basis + transparency | Most member states have analogous monitoring-consultation regimes; confirm locally. |
| UK | Team-only. Named coaching cards: available in v0.7.0 developer mode under the access rules above | UK GDPR lawful basis + DPIA; transparency; ICO employment-monitoring guidance | No works-council co-determination regime, but ICO expects a DPIA and proportionality for monitoring. |
| US (at-will, non-union) | Team-only. Named coaching cards: available in v0.7.0 developer mode under the access rules above | Internal policy; transparency; TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual. | Fewer statutory constraints, but the coaching-not-appraisal stance still applies; state privacy laws may add duties. |
| Anywhere with a collective agreement / union | Follow the agreement | Whatever the agreement requires | A collective bargaining agreement can impose obligations beyond statute regardless of country. |
How to read this table: in every EU/EEA row the safe default is team-only
aggregate reporting plus advance consultation. Run tierd serve with
--aggregation team (the #185 mode), or --aggregation division to roll up one
level higher (#270), so named per-developer views are technically
suppressed — the API, dashboard, and per-developer endpoint never return an
individual name, and sub-k cohorts collapse into "other". Pair that with access
restriction (a read-only viewer token, #190) and separate instances per cohort.
Per-developer deployment in a co-determined jurisdiction should not go live until both (a) the required works-council instrument is in place and (b) a DPIA has been completed. TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual.
Summary
- TIER stores no prompt/completion content, no code, no file contents, outside the free text of raw GitHub webhook payloads (see docs/privacy.md, verified 2026-07-04) — but per-developer cost attribution is still personal data and still triggers labor-law and data-protection duties.
- In DE / FR / NL (and most of the EU/EEA), per-developer measurement is co-determined or consultation-restricted — engage the works council and complete a DPIA before go-live.
- Team-only aggregate reporting is the low-exposure default and is now a
built-in mode (#185): run
tierd serve --aggregation team, or--aggregation divisionto roll up one level higher (#270), with k-anonymity floor--k-anonymity(default 5, hard minimum 3), so the API, dashboard, and per-developer endpoint never surface an individual name to a read-token holder (write-token compliance routes such as the data-subject export still return identifiers by design) and sub-k cohorts collapse into "other"; a sub-k residual is withheld outright, along with the totals that would reconstruct it (#593), so a suppressed response does not reconcile and says so.aggregationis a required setting with no silent default; the localtierd scoreCLI is not gated. - TIER is single-tenant with no cross-team/cross-entity data isolation — separate cohorts by running separate instances; do not claim built-in data segregation. Delegated API scopes do not isolate data from root administrators or host owners.
- TIER is built for coaching, not for evaluating developers. Per-person figures are not accurate enough to judge an individual. TIER cannot enforce an organisation's policy.
- None of the above is legal advice. Consult your counsel, DPO, and works council.
Related
- docs/privacy.md — exactly what TIER reads, stores, and never touches, grounded in the code.
- docs/how-tier-relates.md — why TIER complements DORA / SPACE / DX Core 4 rather than replacing them (reinforces the team-level, non-appraisal framing).
Erased people and later imports (#1491, ruling A⁗)
TIER keeps this record so a completed erasure stays effective. Your organisation decides the legal basis with its counsel.
On an erasure request, if any identifier has an import trace, TIER stores one unlinked keyed hash for each canonical ID, alias and mapped source name. A batch row mapped to someone else is not a trace. If erasure deletes a mapping row whose target is someone else, it also records that source name; a wrong exclusion is reported and reversible. Applied-batch plaintext source-name rows for the erased mapped person are deleted. Retention ageing makes no entry and never deletes entries. The record holds no figures, timestamp or link between identifiers and uses its own HMAC domain. Hashes never appear in API output, logs, audit rows, receipts, previews or data-subject exports. Those compliance artifacts state the record's existence in fixed wording, without checking membership or counting entries.
The record is not anonymous: anyone holding the database could test a guessed identifier. It matches on the identifier alone, so the same identifier from any source is excluded, including a different person. Preview and apply leave a match behind, rechecking inside the apply transaction, with this report line naming nobody: “One or more people were left behind so a completed erasure stays effective.” The bundle is not refused; lookup failure refuses the import. A wrongly excluded person has to come forward because the report names nobody; root can release them. A different (renamed) identifier evades the record. A person erased here with no import trace is not recorded, except this clash case, so a later first import can recreate them. A staged copy can remain for 24 hours.
Entries are kept until root clears them or the database is deleted, with no timer.
A clear removes only the named identifier; a returning person with several
identifiers needs one clear each. Root states either “new consent” or “a different
person with that identifier” (the API value is different person with that identifier).
The response is identical whether or not an entry existed. Each clear is audited
without the identifier, hash or entry count. An audited clear-all states
“our counsel refused this record”. There is no dashboard control. Nothing in the
release waits for counsel, and no Article is cited as the record's legal basis.
The secret and entries share the database file. Entries do not survive a restore
from an older backup that predates them: restoring it loses newer entries and
undoes those erasures. Re-run erasures after a restore.
See the root API commands for one-identifier clear and counsel-refusal clear-all.