Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Project: design a bounded learner-activity release

Last updated: 5 Oct 20265 min read
project
IntermediateBy AITrove Editorial

Build a controlled weekly learning aggregate with explicit permission, bounded contribution, a release ledger and deletion tests.

Create the protected packet

Define learner as the protected unit and weekly qualifying completion as the statistic. Include several events from one learner, a withdrawn learner, an opted-out learner and a duplicate event. Record training and aggregate-release permissions separately. Contribution bounds should reduce one learner to at most one weekly contribution under the chosen contract.

Separate controls from guarantees

Implement deduplication, permission filtering and a transactional release-budget reservation. Use an approved privacy mechanism if the project claims differential privacy; otherwise label the output a bounded internal aggregate without a formal guarantee. Document sensitivity, unit, composition and the number of planned releases before any external publication. The fixture code below is an eligibility check, not a private mechanism.

Exercise operations

Issue two planned ledger reservations and reject a third that exceeds the approved limit. Repeat a request using the same release ID and return the existing approved result rather than drawing a fresh answer. Withdraw learner L-47 during a batch run and verify the tombstone prevents a stale worker from restoring that learner in the next snapshot.

Submit a review packet

Deliver threat model, field inventory, purpose rules, lineage map, bounded-count fixture, budget ledger, deletion-race test and utility report. If using a formal privacy library, include its mechanism configuration and independently reviewed accounting output. State what a membership probe did and did not test. No deployment claim should exceed the evidence in the packet.

Implementation

python
def eligible_learner_count(event_rows, withdrawn_ids):
    withdrawn = set(withdrawn_ids)
    learners = {row["learner_id"] for row in event_rows
                if row["learner_id"] not in withdrawn
                and row["aggregate_permission"] and row["qualifies"]}
    return len(learners)

assert eligible_learner_count([{"learner_id": "L-47", "aggregate_permission": True, "qualifies": True},
                               {"learner_id": "L-47", "aggregate_permission": True, "qualifies": True}], set()) == 1

Performance and operating cost

A scan over N events costs O(N + W) expected time and O(U + W) memory for U eligible learners and W withdrawals. The result is bounded by one contribution per learner in this fixture; it is not differentially private without a reviewed release mechanism.

Common Mistakes

  • Do not call a bounded raw count differentially private.
  • Do not permit an unregistered fresh release after the budget is spent.
  • Do not let a stale batch republish a withdrawn learner.

Read next

Continue the workflow: Project: federated depot model release review.

ai-data
privacy-aware-ml-project
Storage details