From efe75e7949e6bd1fa15560be8ad012d55b50ec70 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Tue, 3 Mar 2026 22:40:19 +0000 Subject: [PATCH 01/21] 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. + <%= 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 02/21] 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 03/21] 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 04/21] 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

+
+
+
+

Terrorism

+ Terrorism is considered a violent action or threat of action, designed to influence a government or intimidate the + public and advance a cause. Online terrorism content is any content made available to others online, which can + encourage or promote terrorism. +
+
+
+
+

Child Sexual Exploitation & Abuse (CSEA)

+
(a) Grooming
+ Grooming is the process of building a relationship or emotional connection with a child or young person so the + perpetrator can manipulate, exploit, and abuse them. +
(b) Image-based Child Sexual Abuse Material (CSAM)
+ Online CSAM includes material depicting sexual activity, or indecent or prohibited imagery of children and can + take the form of photographic images and videos, as well as non-photographic material, such as drawings and + animations. Children themselves may generate content that can be considered CSAM, which can cause them harm. UK + law enforcement refers to this as self-generated indecent imagery (SGII). +
(c) CSAM URLs
+ This is distinct from child sexual abuse material itself in that the content which is shared links to + CSAM rather than containing CSAM itself. +
+
+
+
+

Hate

+ Hate offences can be experienced by many people, in particular minorities and other protected groups. The offences + can be targeted at one or more individuals or wider communities. Online hate content may include threatening or + abusive words, behaviours, images, and other media. The Police and the Crown Prosecution Service (CPS) recognise + hate crime based on race, religion, disability, sexual orientation, and transgender identity. +
+
+
+
+

Harassment, stalking, threats, and abuse

+ The offences of harassment, stalking, threats, and abuse relate to unwanted behaviours that can cause alarm and + distress to other individuals or put them in fear of violence. A case can involve several types of behaviour, + which may include violent threats, cyberstalking, or conduct intended to put a person in fear of violence or cause + serious alarm or distress. +
+
+
+
+

Controlling or coercive behaviour

+ Controlling or coercive behaviour occurs where the victim-survivor and the perpetrator are personally connected, + the perpetrator repeatedly or continuously engages in behaviour that is controlling or coercive, and this + behaviour has a serious effect on the victim-survivor, putting them in fear of violence or causing serious alarm + or distress which has a substantial adverse effect on their usual day-to-day activities.
+
+ Coercive behaviour can be an act (or a pattern of acts) of assault, threats, humiliation and intimidation or other + abuse that is used to harm, punish, or frighten those in intimate or family contexts. Controlling behaviour + includes a range of acts designed to make a person subordinate and/or dependent by isolating them from sources of + support, exploiting their resources and capacities for personal gain, depriving them of the means needed for + independence, resistance, and escape, and regulating their everyday behaviour. +
+
+
+
+

Intimate image abuse

+ Most commonly, an ‘intimate image’ is a photograph or video where the person or people are depicted engaging or + participating or are present during a sexual act and/or where their genitals, buttocks, or breasts are exposed or + covered only with underwear. Intimate image abuse occurs when these intimate images are shared or distributed + without the consent of the person pictured; or when someone threatens to share or distribute these images or + videos without consent. +
+
+
+
+

Extreme pornography

+ ‘Extreme pornography’ is an umbrella term used in UK law to cover several categories of images which are illegal + to possess. Although the legislation varies slightly across legal systems in the UK, extreme pornography broadly + covers images which are produced principally for sexual arousal, and which depict extreme or obscene behaviours. + Possession involves having ‘custody or control’ over the content. Extreme pornographic content includes realistic + and explicit depictions of necrophilia, bestiality, acts threatening a person's life, acts that could result in + serious injury to specific parts of the body, rape, and assault by penetration. +
+
+
+
+

Sexual exploitation of adults

+ Sexual exploitation is the inducement of a commercial sex act generally by means of force, fraud, or coercion. + Online this frequently falls into two distinct categories: (a) individuals who are coerced or forced into sex + work, and (b) consenting adult sex workers who are controlled or exploited by another person. +
+
+
+
+

Human trafficking

+ Human trafficking encompasses a wide range of harmful activities. It can involve modern slavery, and victims and + survivors include adults and children. It is estimated that there were 122,000 people living in modern slavery in + the UK in 2021. Notable forms of human trafficking where harm can manifest online include sexual exploitation and + abuse, forced labour, and criminal exploitation such as county lines exportation of illegal drugs. +
+
+
+
+

Unlawful immigration

+ ‘Illegal entry’ means an individual entering the United Kingdom in breach of a deportation order, entering without + permission to remain, or without entry clearance when the individual needs it. A person commits the offence of + ‘unlawful immigration’ if they do an act which facilitates a breach or attempted breach of immigration law by an + individual who is not a national of the United Kingdom – and where they know or have reasonable cause for + believing this to be the case. It is usually encouraged by organised crime. Online aspects of unlawful immigration + could include the sale of counterfeit travel documents such as passports, visas and identification papers, as well + as the sale of crossings. +
+
+
+
+

Fraud and financial offences

+ Content in this category overlaps strongly with offences related to Proceeds of Crime. Fraud may occur online as + fraud by impersonation or false representation; purchase, investment, romance, or employment scams, or the + recruitment of money mules or launderers. +
+
+
+
+

Proceeds of crime

+ ‘Proceeds of crime’ is the term used for money or assets gained by criminals during their criminal activity and + money laundering. Examples of activities which involve the proceeds of crime online include people being recruited + as money mules to transfer illegally obtained money between bank accounts, discussion between criminals to arrange + money laundering, and stolen personal information (via other criminal activity) offered for sale which can be used + to commit or facilitate other types of fraud. +
+
+
+
+

Drugs and psychoactive substances

+ The supply of drugs and psychoactive substances is facilitated online by enabling suppliers to market their + products and connect with potential buyers. Many of the functionalities of online services that enable suppliers + of legal products to reach, engage and deal directly or indirectly with customers can also be used by those + selling illicit substances. +
+
+
+
+

Firearms, knives, and other weapons

+ The firearms, knives, and other weapons offences cover various matters relating to the online sale of a range of + firearms, knives, and other weapons. In the UK, firearms and certain offensive weapons are classified as restricted + or prohibited. Prohibited firearms and offensive weapons are subject to the strictest limitations on sale. +
+
+
+
+

Encouraging or assisting suicide

+ This offence takes place when an individual intentionally encourages or assists a person to (attempt to) end their + life. Content related to suicide is extremely sensitive; while there may be users who post this content to cause + harm to others, some users may post this content to find supportive communities, to express their own experiences + as part of a healing process or to attempt to help others. Users posting and engaging with this type of content + can include those in vulnerable circumstances who are themselves dealing with thoughts of suicide or self-harm, + as well as those who have recovered or are recovering from mental health challenges. +
+
+
+
+

Foreign interference

+ The new Foreign Interference Offence (FIO) has been designed to tackle malign activity carried out for, or on + behalf of, or intended to benefit, a foreign power. Prohibited conduct captured by this offence will include where + there is a misrepresentation of a person’s identity or purpose, or in the presentation of the information, for + example, through state-backed disinformation campaigns. +
+
+
+
+

Animal cruelty

+ Most acts of cruelty occur offline. The publication online of content relating to or depicting these offline acts + does not in itself cause the animal unnecessary suffering (or further suffering) and therefore cannot constitute + an offence under the Animal Welfare Act. However, the existence of online activities that encourage, assist, or + commit acts of animal cruelty may result in content being made available which may distress a user, or cause them + to engage in harmful or illegal behaviours and activities themselves. +
+
+
+ +

Non-Priority Illegal Content

+
+
+
+

Epilepsy trolling

+ Some individuals with epilepsy may have a physical reaction to online content; they may feel disorientated, + uncomfortable, or unwell after seeing certain images or patterns. The offence is sharing an image with the + intention to cause harm to an individual with epilepsy. +
+
+
+
+

Cyberflashing

+ The cyberflashing offence refers to the sending of a photograph or film of genitals, to cause alarm, distress, or + humiliation, or to obtain sexual gratification. In addition, cyberflashing can form part of a pattern of harmful + behaviour that includes other harms such as cyberstalking, harassment, and/or controlling or coercive behaviour. +
+
+
+
+

Encouraging or assisting serious self-harm

+ This offence takes place when an individual intentionally encourages or assists a person to carry out serious + self-harm. Posting of content that amounts to the offence of encouraging or assisting serious self-harm is often + found in proximity to posting of other types of content related to self-harm that do not amount to the offence. +
+
+
+
+

False communications

+ A person commits the false communications offence if they send a message, with no reasonable excuse to send it, + that they know to be false and intend for that message to cause harm. +
+
+
+
+

Obscene content showing torture of humans and animals

+ This is a non-priority offence covering depictions of cruelty which are so serious as to be obscene, but which may + not amount to another priority offence (such as terrorism or animal cruelty offences). This offence is important + because for pre-recorded content some illegal animal cruelty and human torture content may not necessarily amount + to a priority offence. +
+
+
+
+

Threatening communications

+ A person commits the threatening communications offence if they send a message that conveys a threat of death or + serious harm and, at the time of sending it, the sender intended the individual encountering the message to fear + that the threat would be carried out, or was reckless as to whether the individual encountering the message would + fear that the threat would be carried out. +
+
+
+ +

Service-specific illegal content risks

+

+ Our risk assessment has also identified some additional types of illegal content based on the platform's risk profile. +

+ +
+
+
+

De-anonymisation (“doxxing”)

+ De-anonymisation, known online as “doxxing”, is the posting of a user’s personal information by another user + without permission. This may include a user’s name, home or work address, email address, telephone number, + information about protected characteristics such as sexual orientation, or other personally-identifiable + information. This is often done with the intent to humiliate the victim, but in more serious cases may be done + with the intention to expose the victim to physical harm. +
+
+
+
+

Copyright infringement

+ Copyright infringement may occur online when content is researched or used from elsewhere as part of + user-generated content, in violation of the copyright on that content and not otherwise permitted by fair dealing + exceptions. It is also likely that the use of generative AI models is a strong risk factor for copyright + infringements, as these models often fail to appropriately reference their sources for users to consider whether a + copyright exists. +
+
+
+ +
+ <%= 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

From 829f72a9308a0f6e64cd0f4eea8c84c1780c18b8 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sun, 22 Mar 2026 15:25:54 +0000 Subject: [PATCH 05/21] Finalise training --- app/controllers/complaints_controller.rb | 11 +- app/views/complaints/index.html.erb | 14 +++ .../complaints/training/conclusion.html.erb | 17 +++ .../complaints/training/handling.html.erb | 52 +++++++++ .../complaints/training/higher-risk.html.erb | 100 ++++++++++++++++++ app/views/complaints/training/home.html.erb | 4 +- .../training/illegal-content.html.erb | 61 ++++++++++- config/routes.rb | 1 + ...0260322151439_add_osa_training_to_users.rb | 5 + db/schema.rb | 4 +- 10 files changed, 264 insertions(+), 5 deletions(-) create mode 100644 app/views/complaints/training/conclusion.html.erb create mode 100644 app/views/complaints/training/handling.html.erb create mode 100644 app/views/complaints/training/higher-risk.html.erb create mode 100644 db/migrate/20260322151439_add_osa_training_to_users.rb diff --git a/app/controllers/complaints_controller.rb b/app/controllers/complaints_controller.rb index 953cd9353..700068d73 100644 --- a/app/controllers/complaints_controller.rb +++ b/app/controllers/complaints_controller.rb @@ -3,7 +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] + before_action :training_access, only: [:training, :training_complete] def index render layout: 'without_sidebar' @@ -213,6 +213,15 @@ def training end end + def training_complete + if current_user.update(osa_training: DateTime.now) + flash[:success] = 'Thank you. Your training has been marked as complete.' + else + flash[:danger] = 'Something went wrong. Please tell a staff member about this.' + end + redirect_to safety_center_path + end + private def access_check diff --git a/app/views/complaints/index.html.erb b/app/views/complaints/index.html.erb index 84243a825..b0476f101 100644 --- a/app/views/complaints/index.html.erb +++ b/app/views/complaints/index.html.erb @@ -25,6 +25,20 @@ +
+
+
+

+ <%= link_to osa_training_path('home') do %> + Moderator training » + <% end %> +

+

+ Complete your training for volunteer moderation staff. +

+
+
+
<% if user_signed_in? && current_user.staff? %> diff --git a/app/views/complaints/training/conclusion.html.erb b/app/views/complaints/training/conclusion.html.erb new file mode 100644 index 000000000..b3ebbb9b4 --- /dev/null +++ b/app/views/complaints/training/conclusion.html.erb @@ -0,0 +1,17 @@ +

Last updated 22 March 2026

+ +

Online Safety Act

+

Conclusion

+ +

+ Thank you for taking the time to go through this training. We appreciate that these are often difficult and sensitive + topics, but your understanding and assistance help us to create safe communities for all our users. +

+

+ Please click the button below to mark your training complete. You can come back to these pages at any time from the + Safety Center if you need a reminder. If you need any support, please contact the Community Team. +

+ +<%= form_tag osa_training_complete_path, method: :post do %> + <%= submit_tag 'Mark as complete', class: 'button is-filled is-primary' %> +<% end %> diff --git a/app/views/complaints/training/handling.html.erb b/app/views/complaints/training/handling.html.erb new file mode 100644 index 000000000..423cc4d0e --- /dev/null +++ b/app/views/complaints/training/handling.html.erb @@ -0,0 +1,52 @@ +

Last updated 22 March 2026

+ +

Online Safety Act

+

Handling Illegal Content

+ +

+ It's important that illegal content is handled consistently in order to ensure that we are able to meet the statutory + requirements of us, to protect our users, and to enable us to be transparent with our communities. The way in which + illegal content is handled is set out in our Online Safety & Illegal Content Policy & Procedure, OP02 — you can + find a copy of this here. +

+ +

As a volunteer moderator

+

+ The two ways in which you are likely to come across illegal content as a volunteer moderator are either through + encountering it as you're browsing, or through flags from community members. Either way, our ask of you is the same. + If you believe the content may be illegal: +

+
    +
  • + Delete it, using the "delete" button for the post or comment, to remove it from public view. Deletion doesn't + completely remove a post and leaves it visible for some community members, so in addition: +
  • +
  • + Escalate it to the Community Team. If a community member has flagged the post, you can escalate the flag to us; this + will send an email notifying us. If not, you can ping any of us in Discord, or flag the post yourself and escalate + your own flag to us. +
  • +
+ +

What the Community Team will do

+

+ Making a judgement on whether content constitutes illegal content is surprisingly difficult. Ofcom publishes guidance, + and we have a responsibility to make an initial decision and follow through on that; however, the final say can only + be given by the UK courts. +

+

If our decision is that the content is illegal, we will:

+
    +
  • Use a staff-only "delete for legal reasons" function to remove the post completely.
  • +
  • File an internal report of the content for reporting purposes.
  • +
  • + Notify the author that their content has been removed for this reason. This is a legal requirement. We will not + disclose who has reported or escalated the content report to us. +
  • +
+ +
+ <%= link_to osa_training_path('higher-risk') do %> + Next
+ Higher-Risk Content » + <% end %> +
\ No newline at end of file diff --git a/app/views/complaints/training/higher-risk.html.erb b/app/views/complaints/training/higher-risk.html.erb new file mode 100644 index 000000000..461e50c6d --- /dev/null +++ b/app/views/complaints/training/higher-risk.html.erb @@ -0,0 +1,100 @@ +

Last updated 22 March 2026

+ +

Online Safety Act

+

Higher-Risk Content

+ +

+ Every individual service has an individual risk profile based on its characteristics and demographics as different + functionalities and characteristics raise or lower the likelihood of different types of content. This means that we're + at higher risk of certain types of content than others; we identify and discuss these here. +

+ +

Priority illegal content

+

Terrorism

+

+ While the on-platform impact of terrorism-related content is relatively low, we have a significant number of risk + factors that increase the likelihood of this type of content appearing on the platform. These include: +

+
    +
  • Discussion forums (this is the category of service we fall into under the Act)
  • +
  • Commenting on content
  • +
  • Posting images or videos
  • +
  • Searching user-generated content
  • +
  • Fake or spam profiles
  • +
  • Hyperlinking
  • +
+ +

Hate

+

+ There is no shortage of examples of online platforms where user-to-user interactions have been plagued by hateful + content. There are many places where this has got better, but also plenty where it hasn't. Although we work hard to + foster a sense of community and establish respectful baselines, the risk of this is still present. We've assessed that + this is more likely to occur in comments or user profiles than in post content. As a volunteer moderator, your actions + can set the tone for your community, so you can make the difference in how likely this is to occur. +

+ +

Sexual exploitation of adults

+

+ While we haven't seen any content that we believe to be illegal content under this category, we have seen spam along + closely-related lines. Both here and on other platforms, it's not uncommon to see spam promoting "best escorts in X + city". There is a fine line between this being legal and illegal based on the consent of or impact on those involved, + but if there's any doubt it's safer to escalate for review. This can take the form of spam posts, but more commonly + occurs in spam user profiles, which can be longer-lived. +

+ +

Fraud & financial offences

+

+ This type of content likewise often occurs in spam, both as posts and as user profiles. The more obvious occurrences + may be common scams or offers for illegitimate financial gain, but this category also includes carrying out regulated + acts without being an authorized person or body. This could cover more seemingly innocuous actions, such as users + arranging loans or credit between themselves. +

+ +

Drugs & psychoactive substances

+

+ For this type of content—among others—it's important to remember that discussion of + drugs or psychoactive substances is not necessarily illegal. We also don't currently host any communities that would + be at higher risk of this type of content by the nature of their topic area. Relevant offences include + offering to supply drugs, psychoactive substances, or UK "controlled substances" (which may include medications which + are legal elsewhere in the world); the Act also includes attempting, encouraging, or assisting these offences, which + can be difficult to assess. As with everything, if in doubt please escalate it to us for review. +

+ +

Firearms, knives, and other weapons

+

+ The risks of this type of content are very similar to those of drugs and psychoactive substances, in that discussion + of the topic is not necessarily illegal, and its likelihood may be linked to communities covering related topics. + Our Outdoors community sometimes hosts content discussing tools such as knives which are weapons in other contexts; + these discussions are not necessarily illegal but additional care is required to assess when a line may have been + crossed. If in doubt, escalate! +

+ +

Non-priority illegal content

+

Doxxing

+

+ Doxxing—the deliberate exposure of another user's private information—may fall under a variety of offences + depending on the exact circumstances. Unfortunately, this is something that most online social platforms have to deal + with at some point; we have had one or two such incidents in the past. Doxxing often occurs as part of a wider + campaign of offending against a specific individual known to the perpetrator, or as a result of a particularly heated + disagreement with another user. You can help to avoid the latter of those situations by actively moderating your + community, removing and redirecting disagreements before this becomes a risk, and setting a respectful tone for the + community. +

+ +

Copyright infringement

+

+ This is likewise an unfortunate reality of many online platforms. While professional research communities tend to be + excellent at citing sources and using material appropriately and legally, most of our communities are not at that + level. Users often fall into the trap of thinking "if it's on the Internet, it must be free for anyone to use". UK + "fair dealing" exceptions are stricter and narrower than US "fair use" doctrine, which presents another risk. + Generative AI is also another emerging risk: while we have a + fairly clear policy prohibiting sole AI use, this regularly gets + missed or ignored, and work into appropriately citing sources used in generative AI models is still very young. +

+ +
+ <%= link_to osa_training_path('conclusion') do %> + Next
+ Conclusion » + <% end %> +
\ No newline at end of file diff --git a/app/views/complaints/training/home.html.erb b/app/views/complaints/training/home.html.erb index 0ecadd1af..da90d0a71 100644 --- a/app/views/complaints/training/home.html.erb +++ b/app/views/complaints/training/home.html.erb @@ -6,8 +6,8 @@ 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. + This training should take around an hour to read through all the content. Once you've finished all the modules you'll + be able to mark it as complete, but you'll be able to come back here any time if you need a reminder.

diff --git a/app/views/complaints/training/illegal-content.html.erb b/app/views/complaints/training/illegal-content.html.erb index d55411938..d4951310f 100644 --- a/app/views/complaints/training/illegal-content.html.erb +++ b/app/views/complaints/training/illegal-content.html.erb @@ -1,4 +1,4 @@ -

Last updated 12 March 2026

+

Last updated 22 March 2026

Online Safety Act

Priority & Non-Priority Illegal Content

@@ -9,7 +9,66 @@ content, which details the likelihood and impact of each type of content on our platform specifically.

+

Priority Content

+

+ The Act sets out a number of types of priority illegal content. These are generally the most serious or prevalent + types of illegal content or activity, and the Act requires service providers to take proactive measures to protect + users. This includes risk-assessing, training, and transparency requirements, in addition to the obvious removal of + content. +

+

+ Priority illegal content includes content or activity relating to[1]: +

+
    +
  • child sexual abuse
  • +
  • controlling or coercive behaviour
  • +
  • extreme sexual violence
  • +
  • extreme pornography
  • +
  • fraud
  • +
  • racially or religiously aggravated public order offences
  • +
  • inciting violence
  • +
  • illegal immigration and people smuggling
  • +
  • promoting or facilitating suicide
  • +
  • intimate image abuse
  • +
  • selling illegal drugs or weapons
  • +
  • sexual exploitation
  • +
  • terrorism
  • +
+ +

Non-Priority Content

+

+ Also called "non-designated illegal content", this refers to illegal content which is not related to a priority + offence set out in the Act. This may cover any content which is illegal under UK law, and so this is a very + wide category. The Act specifically defines two new offences as non-priority offences so that they fall into this + category, but also imposes requirements on service providers to assess the risk of other types of non-designated + illegal content which are not specifically mentioned. +

+

+ The two new non-priority offences are: +

+
    +
  • epilepsy trolling
  • +
  • cyberflashing
  • +
+

+ We have also identified risks relating to: +

+
    +
  • copyright infringement
  • +
  • doxxing
  • +
+

+ All of these types of content are defined more fully on the next page. +

+

Footnotes

+
    +
  1. + + https://www.gov.uk/government/publications/online-safety-act-explainer/online-safety-act-explainer#types-of-content-the-act-tackles + +
  2. +
<%= link_to osa_training_path('definitions') do %> diff --git a/config/routes.rb b/config/routes.rb index 4719d354a..2d8ad8ee2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -389,6 +389,7 @@ get 'reports', to: 'complaints#reports', as: :complaints get 'reporting', to: 'complaints#reporting', as: :complaints_reporting get 'training/:page', to: 'complaints#training', as: :osa_training + post 'training/complete', to: 'complaints#training_complete', as: :osa_training_complete end get '403', to: 'errors#forbidden' diff --git a/db/migrate/20260322151439_add_osa_training_to_users.rb b/db/migrate/20260322151439_add_osa_training_to_users.rb new file mode 100644 index 000000000..ced7bfbd1 --- /dev/null +++ b/db/migrate/20260322151439_add_osa_training_to_users.rb @@ -0,0 +1,5 @@ +class AddOsaTrainingToUsers < ActiveRecord::Migration[7.2] + def change + add_column :users, :osa_training, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index ac8ed1016..9aab26649 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: 2026_03_20_104406) do +ActiveRecord::Schema[7.2].define(version: 2026_03_22_151439) do create_table "abilities", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| t.bigint "community_id" t.string "name" @@ -115,6 +115,7 @@ t.index ["community_id"], name: "index_categories_on_community_id" t.index ["default_filter_id"], name: "index_categories_on_default_filter_id" t.index ["license_id"], name: "index_categories_on_license_id" + t.index ["min_view_trust_level"], name: "index_categories_on_min_view_trust_level" t.index ["sequence"], name: "index_categories_on_sequence" t.index ["tag_set_id"], name: "index_categories_on_tag_set_id" end @@ -802,6 +803,7 @@ t.datetime "deleted_at", precision: nil t.bigint "deleted_by_id" t.string "backup_2fa_code" + t.datetime "osa_training" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["deleted_by_id"], name: "index_users_on_deleted_by_id" t.index ["email"], name: "index_users_on_email", unique: true From f4d73cd520412758408f8365159399df9e301a5c Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sun, 22 Mar 2026 15:29:08 +0000 Subject: [PATCH 06/21] Tests --- .../controllers/complaints_controller_test.rb | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/controllers/complaints_controller_test.rb b/test/controllers/complaints_controller_test.rb index 249395b91..79ce44fca 100644 --- a/test/controllers/complaints_controller_test.rb +++ b/test/controllers/complaints_controller_test.rb @@ -346,6 +346,38 @@ class ComplaintsControllerTest < ActionDispatch::IntegrationTest assert_response(:not_found) end + test 'anon should not be able to access training' do + get osa_training_path('home') + assert_response(:not_found) + end + + test 'basic user should not be able to access training' do + sign_in users(:basic_user) + get osa_training_path('home') + assert_response(:not_found) + end + + test 'moderator should be able to access training' do + sign_in users(:moderator) + get osa_training_path('home') + assert_response(:success) + end + + test 'staff should be able to access training' do + sign_in users(:staff) + get osa_training_path('home') + assert_response(:success) + end + + test 'should be able to complete training' do + sign_in users(:staff) + post osa_training_complete_path + assert_response(:found) + assert_redirected_to safety_center_path + assert_equal 'Thank you. Your training has been marked as complete.', flash[:success] + assert_not_nil current_user.osa_training + end + private def try_create_report(**params) From 31fde7987fd9fe45c963869db08e12eee3449382 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sun, 22 Mar 2026 15:33:10 +0000 Subject: [PATCH 07/21] Doh --- test/controllers/complaints_controller_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/controllers/complaints_controller_test.rb b/test/controllers/complaints_controller_test.rb index 79ce44fca..6c663cc5d 100644 --- a/test/controllers/complaints_controller_test.rb +++ b/test/controllers/complaints_controller_test.rb @@ -375,7 +375,7 @@ class ComplaintsControllerTest < ActionDispatch::IntegrationTest assert_response(:found) assert_redirected_to safety_center_path assert_equal 'Thank you. Your training has been marked as complete.', flash[:success] - assert_not_nil current_user.osa_training + assert_not_nil users(:staff).osa_training end private From e5155b71bd1d68194a450aab25b05b9ad6c2d26b Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sat, 28 Mar 2026 17:03:02 +0000 Subject: [PATCH 08/21] Gate OSA training behind a site setting --- app/controllers/complaints_controller.rb | 3 ++- db/seeds/site_settings.yml | 10 ++++++++++ test/controllers/complaints_controller_test.rb | 7 +++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/controllers/complaints_controller.rb b/app/controllers/complaints_controller.rb index 700068d73..395f38a08 100644 --- a/app/controllers/complaints_controller.rb +++ b/app/controllers/complaints_controller.rb @@ -257,7 +257,8 @@ def set_complaint end def training_access - unless user_signed_in? && (current_user.staff? || current_user.at_least_moderator?) + osa_training_enabled = SiteSetting['OSATrainingEnabled'] + unless user_signed_in? && (current_user.staff? || current_user.at_least_moderator?) && osa_training_enabled not_found! end end diff --git a/db/seeds/site_settings.yml b/db/seeds/site_settings.yml index 3c98ad52f..b8d4343d3 100644 --- a/db/seeds/site_settings.yml +++ b/db/seeds/site_settings.yml @@ -862,3 +862,13 @@ description: > Formatting types allowed in post titles. By default, only code, keyboard, and italic are enabled. + +- name: OSATrainingEnabled + value: true + value_type: boolean + category: SafetyCenter + community_id: ~ + description: > + Should Online Safety Act moderator training be available on this instance? + + diff --git a/test/controllers/complaints_controller_test.rb b/test/controllers/complaints_controller_test.rb index 6c663cc5d..d808f0d69 100644 --- a/test/controllers/complaints_controller_test.rb +++ b/test/controllers/complaints_controller_test.rb @@ -369,6 +369,13 @@ class ComplaintsControllerTest < ActionDispatch::IntegrationTest assert_response(:success) end + test 'training should not be accessible if disabled' do + SiteSetting['OSATrainingEnabled'] = false + sign_in users(:staff) + get osa_training_path('home') + assert_response(:not_found) + end + test 'should be able to complete training' do sign_in users(:staff) post osa_training_complete_path From 983fff6bf7b1f981d3101e47565a8d7432f8f43c Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sat, 28 Mar 2026 17:54:01 +0000 Subject: [PATCH 09/21] Make OSA director configurable --- app/views/complaints/training/overview.html.erb | 2 +- db/seeds/site_settings.yml | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/views/complaints/training/overview.html.erb b/app/views/complaints/training/overview.html.erb index 358c61976..17a6baa7d 100644 --- a/app/views/complaints/training/overview.html.erb +++ b/app/views/complaints/training/overview.html.erb @@ -28,7 +28,7 @@ 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. + <%= user_link(User.find(SiteSetting['OSADirector'])) %>.

One of our responsibilities is to ensure that our volunteer moderators (that's you) have an awareness of the Act and diff --git a/db/seeds/site_settings.yml b/db/seeds/site_settings.yml index b8d4343d3..0e989d74b 100644 --- a/db/seeds/site_settings.yml +++ b/db/seeds/site_settings.yml @@ -871,4 +871,10 @@ description: > Should Online Safety Act moderator training be available on this instance? - +- name: OSADirector + value: 8045 + value_type: integer + category: SafetyCenter + community_id: ~ + description: > + The user ID of the Director with responsibility for OSA compliance. From 382f69df66f210302904d2d6c7c157117ce7af2f Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sat, 28 Mar 2026 17:56:24 +0000 Subject: [PATCH 10/21] Clarify county lines --- app/views/complaints/training/definitions.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/complaints/training/definitions.html.erb b/app/views/complaints/training/definitions.html.erb index af53f7170..4ac2f8dda 100644 --- a/app/views/complaints/training/definitions.html.erb +++ b/app/views/complaints/training/definitions.html.erb @@ -103,7 +103,7 @@ Human trafficking encompasses a wide range of harmful activities. It can involve modern slavery, and victims and survivors include adults and children. It is estimated that there were 122,000 people living in modern slavery in the UK in 2021. Notable forms of human trafficking where harm can manifest online include sexual exploitation and - abuse, forced labour, and criminal exploitation such as county lines exportation of illegal drugs. + abuse, forced labour, and criminal exploitation such as "county lines" exportation of illegal drugs.

From 608cf65c69e2d45b9a1c0b4fe41a42827a1c77ef Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sat, 28 Mar 2026 17:57:40 +0000 Subject: [PATCH 11/21] Clarify epilepsy trolling --- app/views/complaints/training/definitions.html.erb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/complaints/training/definitions.html.erb b/app/views/complaints/training/definitions.html.erb index 4ac2f8dda..4ca657e34 100644 --- a/app/views/complaints/training/definitions.html.erb +++ b/app/views/complaints/training/definitions.html.erb @@ -114,7 +114,7 @@ ‘unlawful immigration’ if they do an act which facilitates a breach or attempted breach of immigration law by an individual who is not a national of the United Kingdom – and where they know or have reasonable cause for believing this to be the case. It is usually encouraged by organised crime. Online aspects of unlawful immigration - could include the sale of counterfeit travel documents such as passports, visas and identification papers, as well + could include the sale of counterfeit travel documents such as passports, visas, and identification papers, as well as the sale of crossings.
@@ -192,7 +192,8 @@

Epilepsy trolling

Some individuals with epilepsy may have a physical reaction to online content; they may feel disorientated, uncomfortable, or unwell after seeing certain images or patterns. The offence is sharing an image with the - intention to cause harm to an individual with epilepsy. + intention to cause harm to an individual with epilepsy. This may include bright or flashing videos or images + intended to trigger a physical reaction.
From f1b30b55f5fe1dbca1eee520063e1ffcde5a9c86 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sat, 28 Mar 2026 18:01:20 +0000 Subject: [PATCH 12/21] Make content policy configurable --- app/views/complaints/training/handling.html.erb | 2 +- db/seeds/site_settings.yml | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/views/complaints/training/handling.html.erb b/app/views/complaints/training/handling.html.erb index 423cc4d0e..42309a065 100644 --- a/app/views/complaints/training/handling.html.erb +++ b/app/views/complaints/training/handling.html.erb @@ -7,7 +7,7 @@ It's important that illegal content is handled consistently in order to ensure that we are able to meet the statutory requirements of us, to protect our users, and to enable us to be transparent with our communities. The way in which illegal content is handled is set out in our Online Safety & Illegal Content Policy & Procedure, OP02 — you can - find a copy of this here. + find a copy of this <%= link_to 'here', SiteSetting['ContentPolicyURL'] %>.

As a volunteer moderator

diff --git a/db/seeds/site_settings.yml b/db/seeds/site_settings.yml index 0e989d74b..c4acce09f 100644 --- a/db/seeds/site_settings.yml +++ b/db/seeds/site_settings.yml @@ -877,4 +877,12 @@ category: SafetyCenter community_id: ~ description: > - The user ID of the Director with responsibility for OSA compliance. + The user ID of the Director with responsibility for OSA compliance. + +- name: ContentPolicyURL + value: https://codidact.org/OP02 + value_type: string + category: SafetyCenter + community_id: ~ + description: > + A URL where this instance's online safety & content policy can be found. From 17a4348fb90b2609c6cb212f601a50f2f223bc28 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sat, 28 Mar 2026 18:06:14 +0000 Subject: [PATCH 13/21] Wording updates --- app/views/complaints/training/conclusion.html.erb | 3 ++- app/views/complaints/training/handling.html.erb | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/views/complaints/training/conclusion.html.erb b/app/views/complaints/training/conclusion.html.erb index b3ebbb9b4..c9fd61275 100644 --- a/app/views/complaints/training/conclusion.html.erb +++ b/app/views/complaints/training/conclusion.html.erb @@ -5,7 +5,8 @@

Thank you for taking the time to go through this training. We appreciate that these are often difficult and sensitive - topics, but your understanding and assistance help us to create safe communities for all our users. + topics, but your understanding and assistance help us to create safe communities for all our users. As community + moderators you're likely to see problems before we do, and we appreciate your help in bringing them to our attention.

Please click the button below to mark your training complete. You can come back to these pages at any time from the diff --git a/app/views/complaints/training/handling.html.erb b/app/views/complaints/training/handling.html.erb index 42309a065..98e8e7dcf 100644 --- a/app/views/complaints/training/handling.html.erb +++ b/app/views/complaints/training/handling.html.erb @@ -9,6 +9,10 @@ illegal content is handled is set out in our Online Safety & Illegal Content Policy & Procedure, OP02 — you can find a copy of this <%= link_to 'here', SiteSetting['ContentPolicyURL'] %>.

+

+ We're not asking you, as a volunteer, to make final or legal determinations; we're asking for your assistance in + identifying and escalating content that could violate the law. +

As a volunteer moderator

@@ -18,8 +22,8 @@

  • - Delete it, using the "delete" button for the post or comment, to remove it from public view. Deletion doesn't - completely remove a post and leaves it visible for some community members, so in addition: + Delete it, using the "delete" button for the post or comment, to remove it from public view. This is not intended to + be a final removal, just to restrict its visibility while you also:
  • Escalate it to the Community Team. If a community member has flagged the post, you can escalate the flag to us; this From 8da408869ba5feddd9ad169bc023b205a8c54f18 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sat, 28 Mar 2026 18:19:18 +0000 Subject: [PATCH 14/21] Ignore deprecations for now --- tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 04dd419db..bdbef3116 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,8 @@ "moduleResolution": "node", "noEmit": true, "target": "ES2021", - "types": ["./global.d.ts", "@types/jquery", "moment", "@types/select2"] + "types": ["./global.d.ts", "@types/jquery", "moment", "@types/select2"], + "ignoreDeprecations": "6.0" }, "include": ["./app/assets/javascripts", "./public/assets/community"], "exclude": [ From bb491f7bf48c791b67ab173a54332839331be260 Mon Sep 17 00:00:00 2001 From: ArtOfCode- Date: Sat, 28 Mar 2026 18:32:04 +0000 Subject: [PATCH 15/21] Make messages locale strings --- app/controllers/complaints_controller.rb | 9 ++++++--- config/locales/strings/en.safety_center.yml | 4 ++++ test/controllers/complaints_controller_test.rb | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 config/locales/strings/en.safety_center.yml diff --git a/app/controllers/complaints_controller.rb b/app/controllers/complaints_controller.rb index 395f38a08..57d7ea24b 100644 --- a/app/controllers/complaints_controller.rb +++ b/app/controllers/complaints_controller.rb @@ -214,10 +214,13 @@ def training end def training_complete - if current_user.update(osa_training: DateTime.now) - flash[:success] = 'Thank you. Your training has been marked as complete.' + user_update = current_user.update(osa_training: DateTime.now) + audit_log = AuditLog.moderator_audit(event_type: 'osa_training_completed', user: current_user, + comment: 'OSA training completed.') + if user_update && audit_log + flash[:success] = I18n.t('safety_center.training_complete') else - flash[:danger] = 'Something went wrong. Please tell a staff member about this.' + flash[:danger] = I18n.t('safety_center.training_complete_failed') end redirect_to safety_center_path end diff --git a/config/locales/strings/en.safety_center.yml b/config/locales/strings/en.safety_center.yml new file mode 100644 index 000000000..890913b61 --- /dev/null +++ b/config/locales/strings/en.safety_center.yml @@ -0,0 +1,4 @@ +en: + safety_center: + training_complete: 'Thank you. Your training has been marked as complete.' + training_complete_failed: 'Something went wrong. Please tell a staff member about this.' diff --git a/test/controllers/complaints_controller_test.rb b/test/controllers/complaints_controller_test.rb index d808f0d69..bb23451d0 100644 --- a/test/controllers/complaints_controller_test.rb +++ b/test/controllers/complaints_controller_test.rb @@ -381,7 +381,7 @@ class ComplaintsControllerTest < ActionDispatch::IntegrationTest post osa_training_complete_path assert_response(:found) assert_redirected_to safety_center_path - assert_equal 'Thank you. Your training has been marked as complete.', flash[:success] + assert_equal I18n.t('safety_center.training_complete'), flash[:success] assert_not_nil users(:staff).osa_training end From 4df25d7459852048e2f8bbbe66ab00f64e9e5c6c Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Sat, 28 Mar 2026 21:41:07 +0300 Subject: [PATCH 16/21] Revert "Ignore deprecations for now" This reverts commit 8da408869ba5feddd9ad169bc023b205a8c54f18. --- tsconfig.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index bdbef3116..04dd419db 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,8 +8,7 @@ "moduleResolution": "node", "noEmit": true, "target": "ES2021", - "types": ["./global.d.ts", "@types/jquery", "moment", "@types/select2"], - "ignoreDeprecations": "6.0" + "types": ["./global.d.ts", "@types/jquery", "moment", "@types/select2"] }, "include": ["./app/assets/javascripts", "./public/assets/community"], "exclude": [ From bcc8cfdbffcb86e7f11b4f20470c7094656004ac Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Sat, 28 Mar 2026 22:03:39 +0300 Subject: [PATCH 17/21] Enable tsc & typescript version checks for the typecheck action --- .github/workflows/ci-cd.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 369709f05..bc948af04 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -49,6 +49,8 @@ jobs: with: node-version: 22 - run: npm install + - run: npx tsc -v + - run: npm ls typescript - run: tsc tests: From e3e28c0bb3781fb5e27811241d64afb399233dc9 Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Sat, 28 Mar 2026 22:13:32 +0300 Subject: [PATCH 18/21] Always use clean install in CI --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index bc948af04..06dfae7fa 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -48,7 +48,7 @@ jobs: uses: actions/setup-node@v1 with: node-version: 22 - - run: npm install + - run: npm ci - run: npx tsc -v - run: npm ls typescript - run: tsc From 184f471d79fd2e7321b5dbec2b5682d7f0bdbe2f Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Sat, 28 Mar 2026 22:58:16 +0300 Subject: [PATCH 19/21] Make typecheck action's logs even more verbose --- .github/workflows/ci-cd.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 06dfae7fa..bcece85d1 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -48,7 +48,8 @@ jobs: uses: actions/setup-node@v1 with: node-version: 22 - - run: npm ci + - run: npm ci --verbose + - run: npm ls -g - run: npx tsc -v - run: npm ls typescript - run: tsc From 3ba382c8f9f48047d121f76fa5f385a53053c4cd Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Sat, 28 Mar 2026 23:21:14 +0300 Subject: [PATCH 20/21] Add a direct log of what, exactly, is used for the typecheck action --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index bcece85d1..b7e9f81cc 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -49,9 +49,9 @@ jobs: with: node-version: 22 - run: npm ci --verbose - - run: npm ls -g - run: npx tsc -v - run: npm ls typescript + - run: grep "var version" node_modules/typescript/lib/typescript.js - run: tsc tests: From 9c60499fa9b89c16a065cfa274a1d843ba5ad6e8 Mon Sep 17 00:00:00 2001 From: Oleg Valter Date: Sat, 28 Mar 2026 23:24:26 +0300 Subject: [PATCH 21/21] Typecheck action should use project-local tsc, not whatever is in the path --- .github/workflows/ci-cd.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index b7e9f81cc..c60f2dd49 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -49,10 +49,8 @@ jobs: with: node-version: 22 - run: npm ci --verbose - - run: npx tsc -v - - run: npm ls typescript - - run: grep "var version" node_modules/typescript/lib/typescript.js - - run: tsc + - run: npx tsc --version + - run: npm run typecheck tests: name: Ruby on Rails tests