From efe75e7949e6bd1fa15560be8ad012d55b50ec70 Mon Sep 17 00:00:00 2001
From: ArtOfCode-
Date: Tue, 3 Mar 2026 22:40:19 +0000
Subject: [PATCH 1/4] Add process complaints
---
app/views/complaints/report.html.erb | 11 +++++++++--
config/config/safety_center.yml | 18 ++++++++++++++++--
db/schema.rb | 2 +-
3 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/app/views/complaints/report.html.erb b/app/views/complaints/report.html.erb
index 730ddedba..f608f10eb 100644
--- a/app/views/complaints/report.html.erb
+++ b/app/views/complaints/report.html.erb
@@ -6,7 +6,8 @@
Thank you for taking the time to make a report. If you've seen harmful, abusive, or illegal content on our
communities, you can report this to us here. You can also use this page if you've received a message saying we've
- classified your content as harmful, abusive, or illegal and you wish to contest it.
+ classified your content as harmful, abusive, or illegal and you wish to contest it, or if you have a complaint
+ about our processes or our compliance with our duties.
@@ -45,7 +46,8 @@
<%= label_tag :reported_url, 'Where is this content?' %>
Enter a URL or link to where we can find this content on our network. You can use the Copy Link button under
- posts to get a direct link to a post.
+ posts to get a direct link to a post. Enter N/A if you are not complaining about specific content; add more
+ details below.
<%= text_field_tag :reported_url, nil, class: 'form-element', required: true %>
@@ -95,6 +97,11 @@
Tell us any additional information you have about this report. Is there any additional content we removed that
you would like to include? Provide detailed reasoning explaining why you disagree with our classification.
+
+ Tell us the details of your complaint. Do you believe we have failed to comply with our statutory duties, or
+ that we have failed to follow our policies and procedures? In what way? Provide any relevant examples or
+ evidence.
+
<%= text_area_tag :content, nil, class: 'form-element', required: true, rows: 10 %>
diff --git a/config/config/safety_center.yml b/config/config/safety_center.yml
index dffcad187..10ad2b2e1 100644
--- a/config/config/safety_center.yml
+++ b/config/config/safety_center.yml
@@ -45,16 +45,24 @@ outcomes:
copyright: *illegal_upheld
appeal:
content: our community team agreed with your appeal and have reversed the action taken in your case.
+ process:
+ content: our community team have reviewed your complaint and found information to substantiate it.
+
actionable:
name: Actionable
- description: The content is actionable but the reported classification is not correct. NOT applicable to appeals.
+ description: The content is actionable but the reported classification is not correct. NOT applicable to appeals or
+ process complaints.
user_facing:
illegal: &illegal_actionable
content: our community team agreed that the content you reported was actionable and have taken appropriate
action, but have changed your classification of the content for reporting purposes.
abusive: *illegal_actionable
copyright: *illegal_actionable
- appeal: ~
+ appeal:
+ content: ~
+ process:
+ content: ~
+
disputed:
name: Disputed
description: The reporter's classification is disputed; the content does not appear to be actionable; in the case of
@@ -69,6 +77,8 @@ outcomes:
appeal:
content: our community team have reviewed your appeal and have decided that the action taken in your case was
appropriate.
+ process:
+ content: our community team have reviewed your complaint but found no information to substantiate it.
report_types:
illegal:
@@ -87,6 +97,10 @@ report_types:
enabled: true
name: Classification Appeal
description: an appeal regarding how we've handled your content
+ process:
+ enabled: true
+ name: Complaint about our process
+ description: a complaint about our processes or compliance with our duties
# This list is sourced from Ofcom's list of the 17 types of priority illegal content, which is in turn sourced from
# Schedules 5-7 of the Online Safety Act.
diff --git a/db/schema.rb b/db/schema.rb
index 8752d5420..2278fb412 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.2].define(version: 2025_12_26_185531) do
+ActiveRecord::Schema[7.2].define(version: 2026_02_08_223211) do
create_table "abilities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.bigint "community_id"
t.string "name"
From c2f8fb6512ac12d09a620b61e3fcb73a3e5c7374 Mon Sep 17 00:00:00 2001
From: ArtOfCode-
Date: Thu, 5 Mar 2026 10:46:50 +0000
Subject: [PATCH 2/4] Add broad structure for training
---
app/assets/stylesheets/_variables.scss | 1 +
app/assets/stylesheets/complaints.scss | 41 ++++++++++++++
app/controllers/complaints_controller.rb | 17 ++++++
app/views/complaints/training/home.html.erb | 52 ++++++++++++++++++
app/views/layouts/osa_training.html.erb | 60 +++++++++++++++++++++
config/routes.rb | 1 +
6 files changed, 172 insertions(+)
create mode 100644 app/views/complaints/training/home.html.erb
create mode 100644 app/views/layouts/osa_training.html.erb
diff --git a/app/assets/stylesheets/_variables.scss b/app/assets/stylesheets/_variables.scss
index 51afa04b5..d412b3ec7 100644
--- a/app/assets/stylesheets/_variables.scss
+++ b/app/assets/stylesheets/_variables.scss
@@ -18,6 +18,7 @@ $danger: #EB5959;
$success: #2ECC71;
$info: #58A09A;
$brand: #4B68FF;
+$brand-comp: #F05137;
$data: (
diff --git a/app/assets/stylesheets/complaints.scss b/app/assets/stylesheets/complaints.scss
index fdec7e561..8c679c338 100644
--- a/app/assets/stylesheets/complaints.scss
+++ b/app/assets/stylesheets/complaints.scss
@@ -60,3 +60,44 @@
.is-lead + h1.complaint-title {
margin-top: -1rem;
}
+
+.is-brand-comp {
+ color: $brand-comp;
+}
+
+.with-subtitle {
+ margin-bottom: 0;
+}
+
+.subtitle {
+ margin-top: 0;
+ font-weight: normal;
+ font-size: 1.2rem;
+}
+
+.modules {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
+ gap: 0.5rem;
+}
+
+.module-widget {
+ border: 1px solid $muted-graphic;
+ border-radius: 0.2rem;
+ padding: 0.5rem;
+ color: $key !important;
+
+ > h4 {
+ text-decoration: underline;
+ }
+
+ > p {
+ text-decoration: none;
+ }
+
+ &:hover {
+ background: $primary;
+ color: white !important;
+ text-decoration: none !important;
+ }
+}
diff --git a/app/controllers/complaints_controller.rb b/app/controllers/complaints_controller.rb
index 3d8af4507..953cd9353 100644
--- a/app/controllers/complaints_controller.rb
+++ b/app/controllers/complaints_controller.rb
@@ -3,6 +3,7 @@ class ComplaintsController < ApplicationController
before_action :access_check, only: [:show, :comment]
before_action :write_access_check, only: [:self_assign, :update_status, :change_content_type]
before_action :verify_staff, only: [:reports, :reporting]
+ before_action :training_access, only: [:training]
def index
render layout: 'without_sidebar'
@@ -202,6 +203,16 @@ def reporting
render layout: 'without_sidebar'
end
+ def training
+ pages = Dir.glob(Rails.root.join('app', 'views', 'complaints', 'training', '*.html.erb'))
+ .map { |page| File.basename(page, '.html.erb') }
+ if pages.include?(params[:page])
+ render "complaints/training/#{params[:page]}", layout: 'osa_training'
+ else
+ not_found!
+ end
+ end
+
private
def access_check
@@ -235,4 +246,10 @@ def set_complaint
@complaint
end
+
+ def training_access
+ unless user_signed_in? && (current_user.staff? || current_user.at_least_moderator?)
+ not_found!
+ end
+ end
end
diff --git a/app/views/complaints/training/home.html.erb b/app/views/complaints/training/home.html.erb
new file mode 100644
index 000000000..83d3d3bbb
--- /dev/null
+++ b/app/views/complaints/training/home.html.erb
@@ -0,0 +1,52 @@
+Online Safety Act
+Moderator Training
+
+
+ As part of our responsibilities under the Online Safety Act, we're obligated to provide training to all staff and
+ volunteers undertaking moderation duties.
+
+
+ Take your training here. Completing all the modules will record that you have completed the training, but you can
+ revisit these pages at any time if you need guidance when making moderation decisions.
+
+
+
+ <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+
Overview
+
+ An overview of the Online Safety Act, our duties, and your responsibilities as a volunteer moderator.
+
+ <% end %>
+ <%= link_to osa_training_path('illegal-content'), class: 'module-widget' do %>
+
Priority & Non-Priority Illegal Content
+
+ An explanation of the difference between the 17 types of priority illegal content, and other applicable types of
+ non-priority illegal content.
+
+ <% end %>
+ <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+
Definitions
+
+ Definitions of all the types of illegal content which apply to us.
+
+ <% end %>
+ <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+
Handling Illegal Content
+
+ Your responsibilities and the steps you need to take in response to identifying potentially illegal content.
+
+ <% end %>
+ <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+
Higher-Risk Content
+
+ Some types of content are more likely to occur in our communities than others. More detail on those here.
+
+ <% end %>
+ <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+
Conclusion
+
+ Thank you for taking the time to complete this training. Mark it as complete here and come back here if you need
+ to refer back to it.
+
+ <% end %>
+
diff --git a/app/views/layouts/osa_training.html.erb b/app/views/layouts/osa_training.html.erb
new file mode 100644
index 000000000..54cf9cb66
--- /dev/null
+++ b/app/views/layouts/osa_training.html.erb
@@ -0,0 +1,60 @@
+
+
+
+ <%= render 'layouts/head' %>
+
+
+<%= render 'layouts/header' %>
+
+
+
+
+
+ <%= render 'shared/notices' %>
+
+ <% if @first_visit_notice %>
+ <%= render 'notices/first_visit' %>
+ <% end %>
+
+ <%= yield %>
+
+
+
+
+
+
+
+<%= render 'layouts/footer' %>
+
+<%= render 'layouts/matomo' %>
+
+<% if Rails.env.production? %>
+
+<% end %>
+
+
diff --git a/config/routes.rb b/config/routes.rb
index 05961caad..4719d354a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -388,6 +388,7 @@
post 'report/:token/content_type', to: 'complaints#change_content_type', as: :update_complaint_content_type
get 'reports', to: 'complaints#reports', as: :complaints
get 'reporting', to: 'complaints#reporting', as: :complaints_reporting
+ get 'training/:page', to: 'complaints#training', as: :osa_training
end
get '403', to: 'errors#forbidden'
From adac66e6e516dc3d1ec2cef97825bc3f109693d8 Mon Sep 17 00:00:00 2001
From: ArtOfCode-
Date: Thu, 12 Mar 2026 11:26:18 +0000
Subject: [PATCH 3/4] Overview
---
.../complaints/training/overview.html.erb | 64 +++++++++++++++++++
1 file changed, 64 insertions(+)
create mode 100644 app/views/complaints/training/overview.html.erb
diff --git a/app/views/complaints/training/overview.html.erb b/app/views/complaints/training/overview.html.erb
new file mode 100644
index 000000000..59aee28dc
--- /dev/null
+++ b/app/views/complaints/training/overview.html.erb
@@ -0,0 +1,64 @@
+Last updated 12 March 2026
+
+Online Safety Act
+Overview
+
+
+ The Online Safety Act 2023 (available here) is a law
+ established in the UK in 2023 with the aim of improving online safety, particularly with regard to children, but with
+ wide-ranging effects for all online services. All services with UK users are required to comply with the Act. There
+ are ongoing cases which will define whether this is enforceable on non-UK entities in practice, but because Codidact
+ is a UK-based entity, we are clearly within scope and required to comply.
+
+
+ The Act is enforced by the UK's communications regulator, Ofcom, which also sets out the Register of Risks and Codes
+ of Practice on which our approach is based.
+
+
+Types of service
+
+ The Act defines two types of service: search services and user-to-user services. User-to-user services are those where
+ users may interact with one another; this is where we fall. There are different requirements imposed on each kind of
+ service, which for user-to-user services primarily focus on preventing and removing harmful content, and protecting
+ users from related harms.
+
+
+Our responsibilities
+
+ Responsibility for compliance with the requirements of the Act obviously falls on us (meaning the Codidact Foundation
+ as the organisation running the platform). The Foundation designates one of the Board of Directors as a named
+ individual with ultimate responsibility for compliance with the Act, which is currently
+ ArtOfCode.
+
+
+ One of our responsibilities is to ensure that our volunteer moderators (that's you) have an awareness of the Act and
+ are provided with appropriate training in order to equip them to handle any harmful content which may appear on the
+ platform.
+
+
+Your responsibilities
+
+ As a volunteer moderator, your job is to guide, curate, and set the tone for your community. Part of that job is
+ protecting the community from any unwanted content. The majority of the time, that might take the form of off-topic
+ posts, arguments between users, or handling flags for your attention. Unfortunately, it may also take the form of
+ harmful or illegal content covered by the Act, and one of your responsibilities is to ensure this is dealt with and
+ escalated appropriately.
+
+
+ To be clear: we're not expecting you to handle harmful or illegal content alone. Our ask of you is
+ simple: if you identify something that you think would be covered by the Act, please:
+
+
+ - Delete it to remove it from public view
+ -
+ Escalate it to the Community Team straight away: either ping us in Discord, or flag it yourself and escalate your
+ own flag for us to review.
+
+
+
+
+ <%= link_to osa_training_path('illegal-content') do %>
+ Next
+ Priority & Non-Priority Illegal Content »
+ <% end %>
+
From b3fc44af9f5f93226def698e24757d8d3d0505e0 Mon Sep 17 00:00:00 2001
From: ArtOfCode-
Date: Thu, 12 Mar 2026 20:29:45 +0000
Subject: [PATCH 4/4] Definitions
---
.../complaints/training/definitions.html.erb | 274 ++++++++++++++++++
app/views/complaints/training/home.html.erb | 8 +-
.../training/illegal-content.html.erb | 19 ++
.../complaints/training/overview.html.erb | 2 +-
4 files changed, 298 insertions(+), 5 deletions(-)
create mode 100644 app/views/complaints/training/definitions.html.erb
create mode 100644 app/views/complaints/training/illegal-content.html.erb
diff --git a/app/views/complaints/training/definitions.html.erb b/app/views/complaints/training/definitions.html.erb
new file mode 100644
index 000000000..af53f7170
--- /dev/null
+++ b/app/views/complaints/training/definitions.html.erb
@@ -0,0 +1,274 @@
+Last updated 12 March 2026
+
+Online Safety Act
+Definitions
+
+
+ It is important to understand what each type of content is exactly, so they are defined here. These are definitions
+ which we have written: the Act defines each type of content in terms of related criminal offences, which is more
+ complex than is necessary to deal with the content, so these descriptions are intended to provide a simple overview.
+
+
+Priority Illegal Content
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Non-Priority Illegal Content
+
+
+Service-specific illegal content risks
+
+ Our risk assessment has also identified some additional types of illegal content based on the platform's risk profile.
+
+
+
+
+
+ <%= link_to osa_training_path('handling') do %>
+ Next
+ Handling Illegal Content »
+ <% end %>
+
diff --git a/app/views/complaints/training/home.html.erb b/app/views/complaints/training/home.html.erb
index 83d3d3bbb..0ecadd1af 100644
--- a/app/views/complaints/training/home.html.erb
+++ b/app/views/complaints/training/home.html.erb
@@ -24,25 +24,25 @@
non-priority illegal content.
<% end %>
- <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+ <%= link_to osa_training_path('definitions'), class: 'module-widget' do %>
Definitions
Definitions of all the types of illegal content which apply to us.
<% end %>
- <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+ <%= link_to osa_training_path('handling'), class: 'module-widget' do %>
Handling Illegal Content
Your responsibilities and the steps you need to take in response to identifying potentially illegal content.
<% end %>
- <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+ <%= link_to osa_training_path('higher-risk'), class: 'module-widget' do %>
Higher-Risk Content
Some types of content are more likely to occur in our communities than others. More detail on those here.
<% end %>
- <%= link_to osa_training_path('overview'), class: 'module-widget' do %>
+ <%= link_to osa_training_path('conclusion'), class: 'module-widget' do %>
Conclusion
Thank you for taking the time to complete this training. Mark it as complete here and come back here if you need
diff --git a/app/views/complaints/training/illegal-content.html.erb b/app/views/complaints/training/illegal-content.html.erb
new file mode 100644
index 000000000..d55411938
--- /dev/null
+++ b/app/views/complaints/training/illegal-content.html.erb
@@ -0,0 +1,19 @@
+
Last updated 12 March 2026
+
+Online Safety Act
+Priority & Non-Priority Illegal Content
+
+
+ The Act sets out 17 types of priority illegal content, and a number of types of non-priority illegal content. We have
+ carried out a risk assessment for all types of priority illegal content, and applicable types of non-priority illegal
+ content, which details the likelihood and impact of each type of content on our platform specifically.
+
+
+
+
+
+ <%= link_to osa_training_path('definitions') do %>
+ Next
+ Definitions »
+ <% end %>
+
diff --git a/app/views/complaints/training/overview.html.erb b/app/views/complaints/training/overview.html.erb
index 59aee28dc..358c61976 100644
--- a/app/views/complaints/training/overview.html.erb
+++ b/app/views/complaints/training/overview.html.erb
@@ -1,4 +1,4 @@
-Last updated 12 March 2026
+Last updated 12 March 2026
Online Safety Act
Overview