Skip to content

Data retention policy

Summary

CCiW's data retention policy is to keep personal information only as long as necessary to serve the needs of our campers and officers, and in complicance with all applicable laws. In short:

  • We keep most camper data for 5 years by default, unless deletion is requested earlier. The primary reason for keeping it more than one year is to provide convenience to those booking, so that they do not need to enter all details each year.
  • We keep some basic data about names of campers on camps indefinitely, for legal reasons set out below.
  • We normally keep officer data indefinitely.
  • Data subjects have “right to erasure” as set out in the GDPR and other laws, subject to some limitations below.

Full details are below.

About this document

This is CCiW's official policy on how long we keep personal data in our database, and which data can be deleted at the request of the "data subject" (the person the data is about).

The official source of this document is: https://github.com/cciw-uk/cciw.co.uk/blob/master/config/data_retention.yaml

Formatted version for reading and printing: https://www.cciw.co.uk/data-retention-policy/

The format of this document is "Literate YAML", which means this document is both a human-readable document and a machine-readable file that is automatically read and applied by our software that handles data retention. Sections like this one are 'comments' that are skipped by the software that reads it. The remainder is definitions and instructions that are interpreted and applied by the software.

This format has a lot of advantages:

  • There is no possibility of the CCiW committee updating a policy document but failing to communicate that to the web developers, because there is only a single policy document.
  • This document is automatically checked for validity and completeness. If we add a new table or column in the database, but don't add a retention policy for it here, our automated checks will spot this and force us to define a policy.
  • This document actually is our data retention policy, as opposed to what our policy is supposed to be.

Changes to this document

Where there are implications for the privacy/retention of personal data, changes must only be done with the permission of the CCiW committee, and in conformance with GDPR and other data protection laws.

Structure and contents

We have the following groups of data:

  • Camper and officer data to keep forever
  • Deletable camper and parent booking data
  • Deletable officer data
  • Temporary data
  • Non-personal data

For each group, we start by defining the rules that will be applied, then by listing the tables and columns it applies to.

All groups have an implicit rule: data which is still in use should not be deleted. (For example, the address of a person who still owes us money). Rules for determining which data is in use are not defined in this document.

Deletion mechanisms

There are different ways we could delete data from a database.

  • blanking out details, e.g. replace text with [deleted]. This enables us to keep some details in a row, while removing others, and is usually the preferred method.
  • removing entire rows of data. This generally makes it harder to keep statistics (totals, averages e.g.) about what happened, and we usually prefer not to do this, but where we have no need of the stats it's fine.
  • other more complicated methods, discussed as needed.

Data groups

Camper and officer data to keep forever

The CCiW committee have decided that there is some data that we will keep forever. The main purposes for this are:

  • future legal defence needs for criminal or civil cases
  • being able to cooperate fully and helpfully with any criminal investigations into allegations of abuse or neglect that happened on camp
  • being able to defend the good reputation of CCiW

For these reasons, we need our records to have:

  • complete lists of campers on each camp (with enough names to be able to identify campers)
  • complete lists of officers on each camp
  • information about what medical information parents supplied (needed e.g. for accusations of medical negligence)
  • most officer application form data and all reference data
  • records showing our due diligence regarding DBS checks etc.

As per exceptions allowed in GDPR for these purposes, this policy overrides "right to erasure" of data subjects.

However, CCiW will consider prioritising "right to erasure" even for this data if there are special considerations.

- group: Camper and officer data to keep forever

  rules:
    keep: forever
    deletable on request from data subject: no

  tables:
    - name: bookings.BookingAccount
      # This table stores info about the person making the booking
      columns:
      - name  # full name of the person

    - name: bookings.Booking
      # This table stores the rest of the booking information
      columns:
      - first_name  # of the camper
      - last_name
      - sex

      - camp

      # Medical/dietary/health information:
      - dietary_requirements
      - medical_card_number
      - last_tetanus_injection_date
      - allergies
      - regular_medication_required
      - illnesses
      - can_swim_25m
      - learning_difficulties
      - serious_illness

      # Agreements
      - agreement
      - publicity_photos_agreement
      - custom_agreements_checked

    - name: accounts.User
      # These users are officers/leaders/other CCiW volunteers
      columns:
      - username
      - first_name
      - last_name
      - email  # Email is a useful distinguisher for officers with the same name

    - name: officers.Invitation
      # This stores the link between officers and camps i.e. the officer list
      columns: all

    - name: officers.Application
      # Data entered by officer on application form
      columns:
      - full_name
      - christian_experience
      - youth_experience
      - youth_work_declined
      - youth_work_declined_details
      - relevant_illness
      - illness_details
      - dietary_requirements
      - crime_declaration
      - crime_details
      - court_declaration
      - court_details
      - concern_declaration
      - concern_details
      - allegation_declaration
      - dbs_number
      - dbs_check_consent
      - finished

    - name: officers.Qualification
      # Qualification list that is part of application form
      columns: all

    - name: officers.Referee
      # Referee data entered on the application form
      columns:
      - referee_number
      - name
      - capacity_known
      - address
      - tel
      - mobile
      - email

    - name: officers.Reference
      # Actual reference entered by referee
      columns: all

    - name: officers.DBSCheck
      # This table stores metadata about our DBS check process for each officer,
      # each time we needed to do a check. It does not store copies of the
      # actual result of the DBS check, due to its sensitive nature.
      columns:
      - dbs_number
      - check_type
      - completed
      - requested_by
      - other_organisation
      - applicant_accepted
      - registered_with_dbs_update

Deletable camper and parent booking data

It is useful for campers/parents if we keep booking data for several years, since this will massively speed up the process of them filling in booking forms in subsequent years. But we will delete earlier if requested.

- group: Deletable camper and parent booking data

  rules:
    keep: 5 years
    deletable on request from data subject: yes

  tables:
    - name: bookings.BookingAccount
      columns:
      - email
      - address_line1
      - address_line2
      - address_city
      - address_county
      - address_country
      - address_post_code
      - phone_number
      - share_phone_number
      - email_communication
      - subscribe_to_mailings
      - subscribe_to_newsletter

    - name: bookings.Booking
      columns:
      - date_of_birth
      - address_line1
      - address_line2
      - address_city
      - address_county
      - address_country
      - address_post_code
      - phone_number
      - email
      - church
      - contact_name
      - contact_line1
      - contact_line2
      - contact_city
      - contact_county
      - contact_country
      - contact_post_code
      - contact_phone_number
      - gp_name
      - gp_line1
      - gp_line2
      - gp_city
      - gp_county
      - gp_country
      - gp_post_code
      - gp_phone_number

      deletion methods:
        # It is useful for our statistics and records to know the approx age of
        # campers on camp. So we here configure a custom deletion method that
        # chooses a date of birth that will preserve the calculated "age on
        # camp", but anonymise.
        date_of_birth: preserve age on camp

    - name: ipn.PayPalIPN
      # This contains all the data PayPal sends to us about a payment,
      # some of which are address details that we can remove
      columns:
      # Many of these names are badly chosen (by PayPal)
      - payer_business_name
      - payer_email
      - address_country
      - address_city
      - address_country_code
      - address_name
      - address_state
      - address_status
      - address_street
      - address_zip
      - contact_phone

Deletable camper and parent booking data - supporting information

A second set of camper-related information is "Supporting information". This is almost always documents that relate to a camper's application for custom discounts. We keep this for 3 years, because it relates to finances and as a charity we should keep these records for 3 years.

- group: Deletable camper and parent booking data - supporting information

  rules:
    keep: 3 years
    deletable on request from data subject: no

  tables:
    - name: bookings.SupportingInformation
      columns:
      - from_name
      - from_email
      - from_telephone
      - notes

    - name: bookings.SupportingInformationDocument
      columns:
      - filename
      - mimetype
      - size
      - content

Deleteable officer data

It is usually most useful for us to keep officer data indefinitely, because this avoids officers needing to re-enter data. However, with exceptions noted above, we can observe "right to erasure" for some officer data:

- group: Deleteable officer data

  rules:
    keep: forever  # by default, i.e. indefinitely
    deletable on request from data subject: yes

  tables:
    - name: accounts.User
      columns:
      - password
      - contact_phone_number

    - name: officers.Application
      columns:
      - birth_date
      - birth_place
      - address_firstline
      - address_town
      - address_county
      - address_postcode
      - address_country
      - address_tel
      - address_mobile
      - address_email

Temporary data

Various pieces of data that we don't need forever, and could contain personal data.

- group: Temporary data

  rules:
    keep: 1 year
    deletable on request from data subject: yes

  tables:
    - name: mailer.Message
      # This table stores outgoing emails
      delete row: yes  # Delete entire rows, rather than just blanking out details.
    - name: mailer.MessageLog
      delete row: yes
    - name: contact_us.Message
      # Incoming mails from "contact us" page
      delete row: yes

Non-personal data

This includes:

  • data related to bookings and officers that is not entered by the user themselves, nor is personal in nature, but is internal book-keeping data (first section)
  • many other tables of data for various business purposes

The purpose of listing this is so that we have an exhaustive list of all tables/columns. If any new tables or columns are added to the system, but a policy is not defined in this file, an automatic check will stop deployment until the policy is defined.

- group: Non-personal data

  rules:
    keep: forever
    deletable on request from data subject: no

  tables:
    # -- Data related to personal data, but data that is managed internally --
    - name: bookings.BookingAccount
      columns:
      - total_received
      - created_at
      - first_login
      - last_login
      - last_payment_reminder

    - name: bookings.Booking
      columns:
      - south_wales_transport
      - price_type
      - early_bird_discount
      - booked_at
      - amount_due
      - shelved
      - state
      - created_at
      - booking_expires
      - created_online

    - name: accounts.User
      columns:
      - last_login
      - is_staff
      - is_active
      - date_joined
      - is_superuser
      - bad_password
      - password_validators_used

    - name: cciwmain.Person
      # This table contains information displayed publicly on the website relating
      # to leaders/chaplains on camps.
      columns:
      - name
      - info
      - users

    - name: officers.Application
      columns:
      - date_saved

    - name: bookings.SupportingInformation
      columns:
      - created_at
      - date_received

    - name: bookings.SupportingInformationDocument
      columns:
      - created_at


    # -- Entirely non-personal data --

    # Our tables
    - name: accounts.Role
      columns: all
    - name: bookings.Price
      columns: all
    - name: bookings.Payment
      columns: all
    - name: bookings.ManualPayment
      columns: all
    - name: bookings.RefundPayment
      columns: all
    - name: bookings.WriteOffDebt
      columns: all
    - name: bookings.AccountTransferPayment
      columns: all
    - name: bookings.CustomAgreement
      columns: all
    - name: bookings.SupportingInformationType
      columns: all
    - name: cciwmain.Site
      columns: all
    - name: cciwmain.CampName
      columns: all
    - name: cciwmain.Camp
      columns: all
    - name: sitecontent.MenuLink
      columns: all
    - name: sitecontent.HtmlChunk
      columns: all
    - name: officers.CampRole
      columns: all
    - name: officers.QualificationType
      columns: all
    - name: officers.ReferenceAction
      columns: all
    - name: officers.DBSActionLog
      columns: all
    - name: data_retention.ErasureExecutionLog
      columns: all
    - name: ipn.PayPalIPN
      columns:
      # Column names here are often confusing, this is due
      # to choices by PayPal, not us :-(
      - business  # email address of the person being paid i.e. us
      - charset
      - custom  # contains custom data that links to BookingAccount
      - notify_version
      - parent_txn_id
      - receiver_email
      - receiver_id
      - residence_country
      - test_ipn
      - txn_id
      - txn_type
      - verify_sign
      - first_name
      - last_name
      - payer_id
      - auth_amount
      - auth_exp
      - auth_id
      - auth_status
      - exchange_rate
      - invoice
      - item_name
      - item_number
      - mc_currency
      - mc_fee
      - mc_gross
      - mc_handling
      - mc_shipping
      - memo
      - num_cart_items
      - option_name1
      - option_name2
      - option_selection1
      - option_selection2
      - payer_status
      - payment_date
      - payment_gross
      - payment_status
      - payment_type
      - pending_reason
      - protection_eligibility
      - quantity
      - reason_code
      - remaining_settle
      - settle_amount
      - settle_currency
      - shipping
      - shipping_method
      - tax
      - transaction_entity
      - auction_buyer_id
      - auction_closing_date
      - auction_multi_item
      - for_auction
      - amount
      - amount_per_cycle
      - initial_payment_amount
      - next_payment_date
      - outstanding_balance
      - payment_cycle
      - period_type
      - product_name
      - product_type
      - profile_status
      - recurring_payment_id
      - rp_invoice_id
      - time_created
      - amount1
      - amount2
      - amount3
      - mc_amount1
      - mc_amount2
      - mc_amount3
      - password
      - period1
      - period2
      - period3
      - reattempt
      - recur_times
      - recurring
      - retry_at
      - subscr_date
      - subscr_effective
      - subscr_id
      - username
      - mp_id
      - case_creation_date
      - case_id
      - case_type
      - receipt_id
      - currency_code
      - handling_amount
      - transaction_subject
      - ipaddress
      - flag
      - flag_code
      - flag_info
      - query
      - response
      - created_at
      - updated_at
      - from_view
    # Core django tables
    - name: admin.LogEntry
      columns: all
    - name: auth.Permission
      columns: all
    - name: auth.Group
      columns: all
    - name: contenttypes.ContentType
      columns: all
    - name: sessions.Session
      columns: all
    - name: sites.Site
      columns: all
    # Wiki related tables
    - name: thumbnail.KVStore
      columns: all
    - name: wiki.Article
      columns: all
    - name: wiki.ArticleForObject
      columns: all
    - name: wiki.ArticleRevision
      columns: all
    - name: wiki.ArticlePlugin
      columns: all
    - name: wiki.ReusablePlugin
      columns: all
    - name: wiki.SimplePlugin
      columns: all
    - name: wiki.RevisionPlugin
      columns: all
    - name: wiki.RevisionPluginRevision
      columns: all
    - name: wiki.URLPath
      columns: all
    - name: wiki_attachments.Attachment
      columns: all
    - name: wiki_attachments.AttachmentRevision
      columns: all
    - name: wiki_notifications.ArticleSubscription
      columns: all
    - name: wiki_images.Image
      columns: all
    - name: wiki_images.ImageRevision
      columns: all
    - name: django_nyt.NotificationType
      columns: all
    - name: django_nyt.Settings
      columns: all
    - name: django_nyt.Subscription
      columns: all
    - name: django_nyt.Notification
      columns: all
    # Outgoing emails
    - name: mailer.DontSendEntry
      columns: all
    # Other
    - name: captcha.CaptchaStore
      columns: all