<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://edurange.org/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jwgranville</id>
	<title>EDURange - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://edurange.org/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jwgranville"/>
	<link rel="alternate" type="text/html" href="http://edurange.org/wiki/Special:Contributions/Jwgranville"/>
	<updated>2026-04-03T23:01:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Team_Charter&amp;diff=914</id>
		<title>Team Charter</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Team_Charter&amp;diff=914"/>
		<updated>2026-04-03T21:21:40Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;change me!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See https://www.pmi.org/learning/library/team-charter-development-5128 !&lt;br /&gt;
&lt;br /&gt;
Also:&lt;br /&gt;
&lt;br /&gt;
* https://www.atlassian.com/work-management/project-collaboration/team-charter&lt;br /&gt;
* https://dschool.stanford.edu/tools/design-project-scoping-guide&lt;br /&gt;
* https://ocw.mit.edu/courses/1-040-project-management-spring-2009/&lt;br /&gt;
* https://www.nasa.gov/reference/4-1-stakeholder-expectations-definition/&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=913</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=913"/>
		<updated>2026-04-03T20:42:34Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* The EDURange Project */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the EDURange Wiki. This is less of a formal documentation as it is a living document.&lt;br /&gt;
&lt;br /&gt;
I think that if it&#039;s a choice between losing track of people&#039;s contributions and having a messy wiki, I&#039;d much prefer a messy wiki.  It&#039;s my hope that we can gather all of our notes, thoughts, and loosely related ephemera here, rather than having it scattered across correspondence and various sharing platforms.&lt;br /&gt;
&lt;br /&gt;
We don&#039;t have many conventions yet. Please follow the Golden Rule and treat others as you would be treated. Put your name on your changes. Consider posting to the discussion tab or appending to a page rather than overwriting it. Try not to overwrite the personal work of others.&lt;br /&gt;
&lt;br /&gt;
If it&#039;s installable/runnable/code of any sort, put it on GitHub as well - preferably under the edurange organization so that our future contributors will have seamless access to it too.&lt;br /&gt;
&lt;br /&gt;
Thanks for your time.&lt;br /&gt;
&lt;br /&gt;
~Joe G&lt;br /&gt;
&lt;br /&gt;
== The EDURange Project ==&lt;br /&gt;
[[Team Charter]] - What&#039;s EDURange? What do we do on the EDURange team?&lt;br /&gt;
&lt;br /&gt;
[[:Category:Project History and Roadmaps|Project History and Roadmaps]]&lt;br /&gt;
&lt;br /&gt;
== Developer Links ==&lt;br /&gt;
!!! [[New Version Planning]] !!!&lt;br /&gt;
&lt;br /&gt;
[[Style Guidelines and Developer Tools]]&lt;br /&gt;
&lt;br /&gt;
[[Reference Materials]]&lt;br /&gt;
&lt;br /&gt;
[[:Category:Demonstrations|Demonstrations]]&lt;br /&gt;
&lt;br /&gt;
[[Design Stories (OLD)]]&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Team_Charter&amp;diff=912</id>
		<title>Team Charter</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Team_Charter&amp;diff=912"/>
		<updated>2026-03-31T19:24:54Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;change me!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See https://www.pmi.org/learning/library/team-charter-development-5128 !&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Team_Charter&amp;diff=911</id>
		<title>Team Charter</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Team_Charter&amp;diff=911"/>
		<updated>2026-03-31T19:23:51Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Created page with &amp;quot;change me!&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;change me!&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=910</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=910"/>
		<updated>2026-03-28T16:54:48Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Functional requirements: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives?&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;br /&gt;
*Sample learning objectives:&lt;br /&gt;
**Hierarchically: course/domain; module/unit; learning objective; concept/skill cluster; knowledge components; tasks&lt;br /&gt;
**Scenario (course): Getting Started&lt;br /&gt;
***A learning objective: Students will be able to navigate the filesystem&lt;br /&gt;
****Compose paths&lt;br /&gt;
****Navigate directories&lt;br /&gt;
****Aware of working directory&lt;br /&gt;
****Understand path substitutions (~, ., etc.)&lt;br /&gt;
****etc...&lt;br /&gt;
***A more specific learning objective (or, alternately, a skill cluster): Student will be able to recognize (name) and locate a hidden file in a known directory&lt;br /&gt;
****Give filename of the file in question&lt;br /&gt;
****Identify the path of the file in question&lt;br /&gt;
****Source and provide information about the file, content in the file&lt;br /&gt;
****Differentiate between a file that is and isn&#039;t hidden&lt;br /&gt;
***Task (independent, but linked to learning objectives and knowledge components):&lt;br /&gt;
****Find all the files that end in &amp;quot;.gif&amp;quot; using the find command&lt;br /&gt;
***Knowledge component (independent, linked to tasks):&lt;br /&gt;
****Student uses &#039;find&amp;quot; when searching files&lt;br /&gt;
****Student uses &#039;ls&#039; to list and examine available files&lt;br /&gt;
****Student appropriately applies path prefix (absolute or relative)&lt;br /&gt;
****Student composes valid pattern for file extension&lt;br /&gt;
*Quality of life:&lt;br /&gt;
**Authentication/account naming is a system-wide standard/service&lt;br /&gt;
***How does this behave in designs where students are meant to seize other identities?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
* Two weeks unattended uptime&lt;br /&gt;
* Per-user resource caps configurable per host (if not per-scenario or finer-grained)&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stories: ===&lt;br /&gt;
(Supported use cases, written in terms of the ubiquitous language above)&lt;br /&gt;
* &#039;&#039;&#039;Instructors&#039;&#039;&#039; make &#039;&#039;&#039;Scenarios&#039;&#039;&#039; available to &#039;&#039;&#039;Students&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; configure the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; to support &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; may include a &#039;&#039;&#039;Guide&#039;&#039;&#039; to support exercises and tasks in the &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* The &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; can offer &#039;&#039;&#039;Interventions&#039;&#039;&#039; based on &#039;&#039;&#039;Student&#039;&#039;&#039; performance&lt;br /&gt;
* &#039;&#039;&#039;Students&#039;&#039;&#039; start and stop the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; of &#039;&#039;&#039;Scenarios&#039;&#039;&#039; made accessible to them (the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; does not consume resources when not in use)&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=909</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=909"/>
		<updated>2026-03-28T16:52:24Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* User stories: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives?&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;br /&gt;
*Sample learning objectives:&lt;br /&gt;
**Hierarchically: course/domain; module/unit; learning objective; concept/skill cluster; knowledge components; tasks&lt;br /&gt;
**Scenario (course): Getting Started&lt;br /&gt;
***A learning objective: Students will be able to navigate the filesystem&lt;br /&gt;
****Compose paths&lt;br /&gt;
****Navigate directories&lt;br /&gt;
****Aware of working directory&lt;br /&gt;
****Understand path substitutions (~, ., etc.)&lt;br /&gt;
****etc...&lt;br /&gt;
***A more specific learning objective (or, alternately, a skill cluster): Student will be able to recognize (name) and locate a hidden file in a known directory&lt;br /&gt;
****Give filename of the file in question&lt;br /&gt;
****Identify the path of the file in question&lt;br /&gt;
****Source and provide information about the file, content in the file&lt;br /&gt;
****Differentiate between a file that is and isn&#039;t hidden&lt;br /&gt;
***Task (independent, but linked to learning objectives and knowledge components):&lt;br /&gt;
****Find all the files that end in &amp;quot;.gif&amp;quot; using the find command&lt;br /&gt;
***Knowledge component (independent, linked to tasks):&lt;br /&gt;
****Student uses &#039;find&amp;quot; when searching files&lt;br /&gt;
****Student uses &#039;ls&#039; to list and examine available files&lt;br /&gt;
****Student appropriately applies path prefix (absolute or relative)&lt;br /&gt;
****Student composes valid pattern for file extension&lt;br /&gt;
*Quality of life:&lt;br /&gt;
**Authentication/account naming is a system-wide standard/service&lt;br /&gt;
***How does this behave in designs where students are meant to seize other identities?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
* Two weeks unattended uptime&lt;br /&gt;
* Per-user resource caps configurable per host (if not scenario/finer-grained)&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stories: ===&lt;br /&gt;
(Supported use cases, written in terms of the ubiquitous language above)&lt;br /&gt;
* &#039;&#039;&#039;Instructors&#039;&#039;&#039; make &#039;&#039;&#039;Scenarios&#039;&#039;&#039; available to &#039;&#039;&#039;Students&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; configure the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; to support &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; may include a &#039;&#039;&#039;Guide&#039;&#039;&#039; to support exercises and tasks in the &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* The &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; can offer &#039;&#039;&#039;Interventions&#039;&#039;&#039; based on &#039;&#039;&#039;Student&#039;&#039;&#039; performance&lt;br /&gt;
* &#039;&#039;&#039;Students&#039;&#039;&#039; start and stop the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; of &#039;&#039;&#039;Scenarios&#039;&#039;&#039; made accessible to them (the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; does not consume resources when not in use)&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=908</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=908"/>
		<updated>2026-03-28T16:46:22Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* User stores: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives?&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;br /&gt;
*Sample learning objectives:&lt;br /&gt;
**Hierarchically: course/domain; module/unit; learning objective; concept/skill cluster; knowledge components; tasks&lt;br /&gt;
**Scenario (course): Getting Started&lt;br /&gt;
***A learning objective: Students will be able to navigate the filesystem&lt;br /&gt;
****Compose paths&lt;br /&gt;
****Navigate directories&lt;br /&gt;
****Aware of working directory&lt;br /&gt;
****Understand path substitutions (~, ., etc.)&lt;br /&gt;
****etc...&lt;br /&gt;
***A more specific learning objective (or, alternately, a skill cluster): Student will be able to recognize (name) and locate a hidden file in a known directory&lt;br /&gt;
****Give filename of the file in question&lt;br /&gt;
****Identify the path of the file in question&lt;br /&gt;
****Source and provide information about the file, content in the file&lt;br /&gt;
****Differentiate between a file that is and isn&#039;t hidden&lt;br /&gt;
***Task (independent, but linked to learning objectives and knowledge components):&lt;br /&gt;
****Find all the files that end in &amp;quot;.gif&amp;quot; using the find command&lt;br /&gt;
***Knowledge component (independent, linked to tasks):&lt;br /&gt;
****Student uses &#039;find&amp;quot; when searching files&lt;br /&gt;
****Student uses &#039;ls&#039; to list and examine available files&lt;br /&gt;
****Student appropriately applies path prefix (absolute or relative)&lt;br /&gt;
****Student composes valid pattern for file extension&lt;br /&gt;
*Quality of life:&lt;br /&gt;
**Authentication/account naming is a system-wide standard/service&lt;br /&gt;
***How does this behave in designs where students are meant to seize other identities?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
* Two weeks unattended uptime&lt;br /&gt;
* Per-user resource caps configurable per host (if not scenario/finer-grained)&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stories: ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Instructors&#039;&#039;&#039; make &#039;&#039;&#039;Scenarios&#039;&#039;&#039; available to &#039;&#039;&#039;Students&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; configure the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; to support &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; may include a &#039;&#039;&#039;Guide&#039;&#039;&#039; to support exercises and tasks in the &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* The &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; can offer &#039;&#039;&#039;Interventions&#039;&#039;&#039; based on &#039;&#039;&#039;Student&#039;&#039;&#039; performance&lt;br /&gt;
* &#039;&#039;&#039;Students&#039;&#039;&#039; start and stop the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; of &#039;&#039;&#039;Scenarios&#039;&#039;&#039; made accessible to them (the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; does not consume resources when not in use)&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=907</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=907"/>
		<updated>2026-03-27T22:01:33Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives?&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;br /&gt;
*Sample learning objectives:&lt;br /&gt;
**Hierarchically: course/domain; module/unit; learning objective; concept/skill cluster; knowledge components; tasks&lt;br /&gt;
**Scenario (course): Getting Started&lt;br /&gt;
***A learning objective: Students will be able to navigate the filesystem&lt;br /&gt;
****Compose paths&lt;br /&gt;
****Navigate directories&lt;br /&gt;
****Aware of working directory&lt;br /&gt;
****Understand path substitutions (~, ., etc.)&lt;br /&gt;
****etc...&lt;br /&gt;
***A more specific learning objective (or, alternately, a skill cluster): Student will be able to recognize (name) and locate a hidden file in a known directory&lt;br /&gt;
****Give filename of the file in question&lt;br /&gt;
****Identify the path of the file in question&lt;br /&gt;
****Source and provide information about the file, content in the file&lt;br /&gt;
****Differentiate between a file that is and isn&#039;t hidden&lt;br /&gt;
***Task (independent, but linked to learning objectives and knowledge components):&lt;br /&gt;
****Find all the files that end in &amp;quot;.gif&amp;quot; using the find command&lt;br /&gt;
***Knowledge component (independent, linked to tasks):&lt;br /&gt;
****Student uses &#039;find&amp;quot; when searching files&lt;br /&gt;
****Student uses &#039;ls&#039; to list and examine available files&lt;br /&gt;
****Student appropriately applies path prefix (absolute or relative)&lt;br /&gt;
****Student composes valid pattern for file extension&lt;br /&gt;
*Quality of life:&lt;br /&gt;
**Authentication/account naming is a system-wide standard/service&lt;br /&gt;
***How does this behave in designs where students are meant to seize other identities?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
* Two weeks unattended uptime&lt;br /&gt;
* Per-user resource caps configurable per host (if not scenario/finer-grained)&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Instructors&#039;&#039;&#039; make &#039;&#039;&#039;Scenarios&#039;&#039;&#039; available to &#039;&#039;&#039;Students&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; configure the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; to support &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; may include a &#039;&#039;&#039;Guide&#039;&#039;&#039; to support exercises and tasks in the &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* The &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; can offer &#039;&#039;&#039;Interventions&#039;&#039;&#039; based on &#039;&#039;&#039;Student&#039;&#039;&#039; performance&lt;br /&gt;
* &#039;&#039;&#039;Students&#039;&#039;&#039; start and stop the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; of &#039;&#039;&#039;Scenarios&#039;&#039;&#039; made accessible to them (the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; does not consume resources when not in use)&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=906</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=906"/>
		<updated>2026-03-27T22:00:35Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives?&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;br /&gt;
*Sample learning objectives:&lt;br /&gt;
**Hierarchically: course/domain; module/unit; learning objective; concept/skill cluster; knowledge components; tasks&lt;br /&gt;
**Scenario (course): Getting Started&lt;br /&gt;
***A learning objective: Students will be able to navigate the filesystem&lt;br /&gt;
****Compose paths&lt;br /&gt;
****Navigate directories&lt;br /&gt;
****Aware of working directory&lt;br /&gt;
****Understand path substitutions (~, ., etc.)&lt;br /&gt;
****etc...&lt;br /&gt;
***A more specific learning objective: Student will be able to recognize (name) and locate a hidden file in a known directory&lt;br /&gt;
****Give filename of the file in question&lt;br /&gt;
****Identify the path of the file in question&lt;br /&gt;
****Source and provide information about the file, content in the file&lt;br /&gt;
****Differentiate between a file that is and isn&#039;t hidden&lt;br /&gt;
***Task (independent, but linked to learning objectives and knowledge components):&lt;br /&gt;
****Find all the files that end in &amp;quot;.gif&amp;quot; using the find command&lt;br /&gt;
***Knowledge component (independent, linked to tasks):&lt;br /&gt;
****Student uses &#039;find&amp;quot; when searching files&lt;br /&gt;
****Student uses &#039;ls&#039; to list and examine available files&lt;br /&gt;
****Student appropriately applies path prefix (absolute or relative)&lt;br /&gt;
****Student composes valid pattern for file extension&lt;br /&gt;
*Quality of life:&lt;br /&gt;
**Authentication/account naming is a system-wide standard/service&lt;br /&gt;
***How does this behave in designs where students are meant to seize other identities?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
* Two weeks unattended uptime&lt;br /&gt;
* Per-user resource caps configurable per host (if not scenario/finer-grained)&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Instructors&#039;&#039;&#039; make &#039;&#039;&#039;Scenarios&#039;&#039;&#039; available to &#039;&#039;&#039;Students&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; configure the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; to support &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; may include a &#039;&#039;&#039;Guide&#039;&#039;&#039; to support exercises and tasks in the &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* The &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; can offer &#039;&#039;&#039;Interventions&#039;&#039;&#039; based on &#039;&#039;&#039;Student&#039;&#039;&#039; performance&lt;br /&gt;
* &#039;&#039;&#039;Students&#039;&#039;&#039; start and stop the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; of &#039;&#039;&#039;Scenarios&#039;&#039;&#039; made accessible to them (the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; does not consume resources when not in use)&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=905</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=905"/>
		<updated>2026-03-24T20:04:25Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* User stores: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives?&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Instructors&#039;&#039;&#039; make &#039;&#039;&#039;Scenarios&#039;&#039;&#039; available to &#039;&#039;&#039;Students&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; configure the &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; to support &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Scenarios&#039;&#039;&#039; may include a &#039;&#039;&#039;Guide&#039;&#039;&#039; to support exercises and tasks in the &#039;&#039;&#039;Learning Objectives&#039;&#039;&#039;&lt;br /&gt;
* The &#039;&#039;&#039;Learning Environment&#039;&#039;&#039; can offer &#039;&#039;&#039;Interventions&#039;&#039;&#039; based on &#039;&#039;&#039;Student&#039;&#039;&#039; performance&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=904</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=904"/>
		<updated>2026-03-24T20:01:53Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* User stores: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives?&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Instructors&#039;&#039;&#039; make &#039;&#039;&#039;Scenarios&#039;&#039;&#039; available to &#039;&#039;&#039;Students&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=903</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=903"/>
		<updated>2026-03-24T20:01:17Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* User stores: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives?&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;br /&gt;
&lt;br /&gt;
* Instructors make Scenarios available to Students&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=902</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=902"/>
		<updated>2026-03-24T19:58:35Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Ubiquitous language: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
*** Do these have sufficient resolution to see why/how students arrived at a correct answer?&lt;br /&gt;
** What are indicators of student progress on learning objectives?&lt;br /&gt;
*** How do events (such as those matched by milestones) correlate with questions?&lt;br /&gt;
**** What are students asking about in help requests?&lt;br /&gt;
**** Can we select semantics from log data (commands, chat, questions)?&lt;br /&gt;
** How do we know tangibly that a student is completing learning-related tasks?&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
** Underlying system state?&lt;br /&gt;
*** What denotes/distinguishes a command?&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;br /&gt;
&lt;br /&gt;
* How do we assess correctness/domain truth in a model of learning objectives:&lt;br /&gt;
** Navigating a filesystem:&lt;br /&gt;
*** &amp;quot;Can a student navigate the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Can the student compose an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student use / to begin an absolute path?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student refer to directories present at the root of the filesystem?&amp;quot;&lt;br /&gt;
**** &amp;quot;Do they correctly use find?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student map correctly between paths and the purposes of the file hierarchy?&amp;quot;&lt;br /&gt;
***** &amp;quot;Does the student look for binaries in /bin/?&amp;quot;&lt;br /&gt;
**** &amp;quot;Does the student use ~ to refer to their home directory?&amp;quot;&lt;br /&gt;
*** What artifacts help to assess this?&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=901</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=901"/>
		<updated>2026-02-22T19:01:26Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Remove derelict/unpopulated pages and miscategorized/orphaned content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the EDURange Wiki. This is less of a formal documentation as it is a living document.&lt;br /&gt;
&lt;br /&gt;
I think that if it&#039;s a choice between losing track of people&#039;s contributions and having a messy wiki, I&#039;d much prefer a messy wiki.  It&#039;s my hope that we can gather all of our notes, thoughts, and loosely related ephemera here, rather than having it scattered across correspondence and various sharing platforms.&lt;br /&gt;
&lt;br /&gt;
We don&#039;t have many conventions yet. Please follow the Golden Rule and treat others as you would be treated. Put your name on your changes. Consider posting to the discussion tab or appending to a page rather than overwriting it. Try not to overwrite the personal work of others.&lt;br /&gt;
&lt;br /&gt;
If it&#039;s installable/runnable/code of any sort, put it on GitHub as well - preferably under the edurange organization so that our future contributors will have seamless access to it too.&lt;br /&gt;
&lt;br /&gt;
Thanks for your time.&lt;br /&gt;
&lt;br /&gt;
~Joe G&lt;br /&gt;
&lt;br /&gt;
== The EDURange Project ==&lt;br /&gt;
[[:Category:Project History and Roadmaps|Project History and Roadmaps]]&lt;br /&gt;
&lt;br /&gt;
== Developer Links ==&lt;br /&gt;
!!! [[New Version Planning]] !!!&lt;br /&gt;
&lt;br /&gt;
[[Style Guidelines and Developer Tools]]&lt;br /&gt;
&lt;br /&gt;
[[Reference Materials]]&lt;br /&gt;
&lt;br /&gt;
[[:Category:Demonstrations|Demonstrations]]&lt;br /&gt;
&lt;br /&gt;
[[Design Stories (OLD)]]&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=900</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=900"/>
		<updated>2026-02-17T19:10:39Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Functional requirements: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently, 500+ at large institutions?&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=899</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=899"/>
		<updated>2026-01-24T01:34:52Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Functional requirements: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* Physical systems: controlled via ordinary SSH, provisioned with PXE or other net boot methods?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=898</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=898"/>
		<updated>2026-01-24T01:31:05Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Ubiquitous language: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Students will be able to log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=897</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=897"/>
		<updated>2026-01-24T01:28:38Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Functional requirements: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
* Telemetry layer for instrument/orchestration health&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=896</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=896"/>
		<updated>2026-01-24T01:21:43Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Ubiquitous language: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
* Telemetry layer for instrument/orchestration help&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance], [https://www.cosmicpython.com/book/preface.html Cosmic Python] or [https://www.domainlanguage.com/ddd/ DDD Resources - Domain Language])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=895</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=895"/>
		<updated>2026-01-24T01:18:05Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Developer Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the EDURange Wiki. This is less of a formal documentation as it is a living document.&lt;br /&gt;
&lt;br /&gt;
I think that if it&#039;s a choice between losing track of people&#039;s contributions and having a messy wiki, I&#039;d much prefer a messy wiki.  It&#039;s my hope that we can gather all of our notes, thoughts, and loosely related ephemera here, rather than having it scattered across correspondence and various sharing platforms.&lt;br /&gt;
&lt;br /&gt;
We don&#039;t have many conventions yet. Please follow the Golden Rule and treat others as you would be treated. Put your name on your changes. Consider posting to the discussion tab or appending to a page rather than overwriting it. Try not to overwrite the personal work of others.&lt;br /&gt;
&lt;br /&gt;
If it&#039;s installable/runnable/code of any sort, put it on GitHub as well - preferably under the edurange organization so that our future contributors will have seamless access to it too.&lt;br /&gt;
&lt;br /&gt;
Thanks for your time.&lt;br /&gt;
&lt;br /&gt;
~Joe G&lt;br /&gt;
&lt;br /&gt;
== The EDURange Project ==&lt;br /&gt;
[[:Category:Project History and Roadmaps|Project History and Roadmaps]]&lt;br /&gt;
&lt;br /&gt;
== Developer Links ==&lt;br /&gt;
!!! [[New Version Planning]] !!!&lt;br /&gt;
&lt;br /&gt;
[[Style Guidelines and Developer Tools]]&lt;br /&gt;
&lt;br /&gt;
[[Reference Materials]]&lt;br /&gt;
&lt;br /&gt;
[[:Category:Demonstrations|Demonstrations]]&lt;br /&gt;
&lt;br /&gt;
[[Design Stories (OLD)]]&lt;br /&gt;
&lt;br /&gt;
[[Interface Design]]&lt;br /&gt;
&lt;br /&gt;
[[Scenario Creation Guide]]&lt;br /&gt;
&lt;br /&gt;
[[Terraform Design]]&lt;br /&gt;
&lt;br /&gt;
[[Hosting Requirements]]&lt;br /&gt;
&lt;br /&gt;
[[Domain Modeling]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We&#039;re still figuring out Media Wiki, so I kept the following...&lt;br /&gt;
&lt;br /&gt;
== Orphaned Default Media Wiki Content ==&lt;br /&gt;
&amp;lt;strong&amp;gt;Welcome to the EDURange Wiki&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Consult the [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents User&#039;s Guide] for information on using the wiki software.&lt;br /&gt;
&lt;br /&gt;
== Getting started with Media Wiki ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Configuration settings list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]&lt;br /&gt;
* [https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/ MediaWiki release mailing list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=894</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=894"/>
		<updated>2026-01-24T00:54:52Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
* Telemetry layer for instrument/orchestration help&lt;br /&gt;
* Students are provided a learning environment that is safe to explore/attack without threatening the application host infrastructure&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=893</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=893"/>
		<updated>2026-01-24T00:48:55Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;As we&#039;re still getting started, please feel free to insert notes and comments where you like - just try to avoid changing or deleting things you yourself didn&#039;t write. We&#039;ll come up with a shared structure as we go. Also consider using the &amp;quot;discussion&amp;quot; tab at the top if you aren&#039;t sure where to comment or want to have a dialogue.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These items at the top are on the agenda for discussion, but don&#039;t have a clear place they belong yet:&lt;br /&gt;
* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
* Telemetry layer for instrument/orchestration help&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
(See [https://agilealliance.org/glossary/ubiquitous-language/ What is Ubiquitous Language? | Agile Alliance])&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=892</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=892"/>
		<updated>2026-01-23T21:30:06Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
* Telemetry layer for instrument/orchestration help&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** e.g.&lt;br /&gt;
*** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
*** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=891</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=891"/>
		<updated>2026-01-23T21:18:26Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
* Telemetry layer for instrument/orchestration help&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=890</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=890"/>
		<updated>2026-01-23T21:16:48Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Ubiquitous language: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
* How to refer to observation/logging instruments&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
* Observability/instrumentation? (Name?)&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=889</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=889"/>
		<updated>2026-01-23T21:13:42Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
* Staged/prerequisite content in guide/scenario&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=888</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=888"/>
		<updated>2026-01-23T21:09:47Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Add learning objective examples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** &amp;quot;Students will be able to use ls to list the contents of a directory&amp;quot;&lt;br /&gt;
** &amp;quot;Student can log in to the exercise via SSH&amp;quot;&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=887</id>
		<title>New Version Planning</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=New_Version_Planning&amp;diff=887"/>
		<updated>2026-01-23T20:59:49Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Starting page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* POST handler/API reachability&lt;br /&gt;
* Chat capability&lt;br /&gt;
* Containers&lt;br /&gt;
* NSJail, chroot?&lt;br /&gt;
* How to model shared resources and contention?&lt;br /&gt;
&lt;br /&gt;
=== Functional requirements: ===&lt;br /&gt;
&lt;br /&gt;
* 20-300 students simultaneously? Semi-simultaneously? ~150 concurrently&lt;br /&gt;
&lt;br /&gt;
=== Ubiquitous language: ===&lt;br /&gt;
&lt;br /&gt;
* Scenario&lt;br /&gt;
* Learning objectives&lt;br /&gt;
** Milestone&lt;br /&gt;
* Questions (are exercises distinct?)&lt;br /&gt;
* Guide&lt;br /&gt;
** Guide section&lt;br /&gt;
* Student&lt;br /&gt;
* Instructor&lt;br /&gt;
* Hint&lt;br /&gt;
* Intervention&lt;br /&gt;
* Prediction&lt;br /&gt;
* Learning environment&lt;br /&gt;
&lt;br /&gt;
=== User stores: ===&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=886</id>
		<title>TTY Logging with BPF</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=886"/>
		<updated>2025-08-20T02:23:53Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Demonstrations]]&lt;br /&gt;
See https://github.com/edurange/demo-bpf-tty-logger.&lt;br /&gt;
&lt;br /&gt;
Demonstrates how to capture TTY activity using BPF kernel probes.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
To run it one needs to have superuser privileges (for kernel access). The probes intercept all TTY activity on the host system - both inside and outside of containers. If the script is printing to a TTY device the prints themselves will also be observed, creating a feedback loop that will quickly consume the kernel buffers. As such the output should be redirected to a file. I recommend redirecting both STDOUT and STDERR as follows:&lt;br /&gt;
 sudo python3 [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] &amp;amp;&amp;gt; log&lt;br /&gt;
&lt;br /&gt;
== Explanation ==&lt;br /&gt;
[https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] is compact but there&#039;s a lot going on. Unlike [https://ttylog.sourceforge.net ttylog] and [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/analyze.py analyze.py], which it would replace, [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] does not rely on changing or proxying the TTY device itself. Rather, it utilizes [[wikipedia:Berkeley_Packet_Filter|Berkeley Packet Filters]], a kernel-level interface for hooking code into system calls; see also https://www.kernel.org/doc/html/latest/bpf/index.html for a specific implementation of the BPF interface. Instead of intercepting at the point of the TTY connection, we tamper with and tap the kernel calls that provide TTY services system-wide.&lt;br /&gt;
&lt;br /&gt;
=== Berkeley Packet Filter ===&lt;br /&gt;
BPF links compiled object code into the kernel. Newer extensions to BPF support using pre-compiled code payloads, but typically the code is loaded at runtime from C, with a tool such as [https://root.cern/cling/ cling]. It looks odd by Python standards, but the common practice is to embed a one-file C program as a string in the Python file, then send it to be compiled and linked in through the BPF API.&lt;br /&gt;
&lt;br /&gt;
The main area of interest are the functions injected into the kernel, called probes - kprobe__tty_write() and kprobe__n_tty_receive_buf_common(). The prefix &amp;quot;kprobe__&amp;quot; tells BPF to use these functions as probes automatically (but it&#039;s possible to use arbitrary functions, with an additional call to identify them.)&lt;br /&gt;
&lt;br /&gt;
tty_write() and tty_receive_buf_common() are used to copy data in and out of kernel memory, as user-land processes talk to the physical device drivers represented in software by the TTY resource. In its basic usage, BPF calls the probe with the same parameters that the system call received. We use this to read the data buffers as TTY devices transmit and receive.&lt;br /&gt;
&lt;br /&gt;
To safely permit alterations to the kernel, BPF enforces safety checks above and beyond normal C language requirements. As such, the kernel probe code may appear pedantic in the amount of guards used. These are necessary for approval by the BPF checker.&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
BPF lacks a wall clock time source. In other words, all of the time values available in the kernel under BPF are based on the system&#039;s uptime clock, not a time source synced to time of day. The uptime clocks have some unusual behavior compared to typical clocks. When the host system is halted or put to sleep, the clocks stop. From the perspective of software running on the host system, the system clocks move forward at a smooth rate, but the wall clock time jumps forward unpredictably whenever the system wakes from sleep.&lt;br /&gt;
&lt;br /&gt;
To account for this, first the raw time values must be captured as close to the actual TTY event as possible - preferably, as the first instruction in the probe. We note the system time as part of the record of the TTY event, which is then exfiltrated from the kernel using a shared memory buffer provided by BPF.&lt;br /&gt;
&lt;br /&gt;
In user space a handler function in the outer Python script reads events from the BPF buffer. There we have full access to wall clock time. Measuring the difference between system uptime and wall clock time is as simple as capturing both values, but it may occasionally jump as a result of changes to the offset value used to calibrate it - such as when the system receives a time update via network time protocol, which can occur quite frequently on modern operating systems.&lt;br /&gt;
&lt;br /&gt;
To watch for drift in the clock offset, we take the difference between the current system-wide wall clock time and the time extrapolated by adding our offset estimate to the most recent timestamp. If the drift between the two time sources exceeds some small threshhold, we calculate a new offset value. We also recalibrate the offset value on a regular interval, even if it doesn&#039;t exceed the drift limit. In our implementation we chose a drift threshold of one thousandth of a second, and a refresh timeout of one minute.&lt;br /&gt;
&lt;br /&gt;
The timing values are captured in a closure to avoid reliance on mutable global variables. calibratetimefactory() encloses the timing values with the method that updates them. API consumers need only call the resulting calibratetime() function to receive updated timing information, while being discouraged from tampering with the internal representation and underlying algorithm.&lt;br /&gt;
&lt;br /&gt;
=== Event Attributes ===&lt;br /&gt;
As mentioned, because this code runs in the kernel whenever the relevant system calls are invoked, it sees all TTY activity - from all processes and all users. Unlike ttylog, we are not attached to one particular TTY device. To distinguish between calls made by different services on behalf of different endpoints, we must record additional data about each system call event.&lt;br /&gt;
&lt;br /&gt;
In the order that they appear in the code, not necessarily by relevance:&lt;br /&gt;
&lt;br /&gt;
- `rawtime`: The raw value of the system uptime clock when the event was captured. Represented as nanoseconds of CPU runtime since boot up. A &amp;quot;monotonic clock&amp;quot; in hardware design terminology.&lt;br /&gt;
&lt;br /&gt;
- `cgid`: The &amp;quot;**C**ontrol **G**roup **ID**&amp;quot; (sometimes shortened &amp;quot;Cgroup&amp;quot;) is a Linux mechanism for grouping processes and other resources heirarchically. It can be used in some circumstances to identify processes as belonging to containers. Cgroups are a Linux kernel feature that do not have a direct analog on other POSIX systems, but so is BPF, so while I&#039;d like to stick to POSIX compatibility where possible that&#039;s just not relevant in this context.&lt;br /&gt;
&lt;br /&gt;
- `inode`: The &amp;quot;**i**ndex **node**&amp;quot; refers to the file-like object associated with the TTY device or psuedoterminal that is transmitting/receiving. This is a primary source of identifying information for our purposes, but there are some circumstances where it isn&#039;t available, and there are also cases where inode values will differ but we want to associate the data together anyways, such as when we see the same student log in on more than one terminal.&lt;br /&gt;
&lt;br /&gt;
- `pidtgid`: This encodes two values which come from BPF packed into a single variable - PID, the &amp;quot;**p**rocess **ID**&amp;quot; of the main thread, and TGID, the &amp;quot;**t**hread **g**roup **ID**&amp;quot;, which may contain a different ID for the current thread if the process has more than just a main thread.&lt;br /&gt;
&lt;br /&gt;
- `nsid`: This contains the &amp;quot;**n**ame**s**pace **ID**&amp;quot; of the calling process, which can help to identify containerized processes in some circumstances where CGID and PID/TGID leave ambiguity.&lt;br /&gt;
&lt;br /&gt;
- `comm`: This is the &amp;quot;**comm**and name&amp;quot;, a fixed-length 15-character identifier of the calling process. It is often not unique, and sometimes truncated and/or mangled, but may provide additional context in some situations and enhances the human readability of events.&lt;br /&gt;
&lt;br /&gt;
- `buf`: This is the &amp;quot;**buf**fer&amp;quot;. This is the C byte array that the kernel received from the caller, representing the data being communicated. It may be as long as a kernel page, which is 4kB on contemporary systems, and may or may not be null-terminated. The buffer contains raw bytes that have not been interpreted according to any text encoding, and in some cases the buffer will not be decodable by itself - multi-byte characters (like from Unicode) are not guaranteed to be complete and may be split between two buffer flushes. What this means is that text needs to be assembled and decoded at a higher level than we are working at while just capturing the data.&lt;br /&gt;
&lt;br /&gt;
- `len`: The number of bytes in the buffer. Not the same as the characters represented in the buffer. Definitely not the same as the number of characters that will show up on the terminal.&lt;br /&gt;
&lt;br /&gt;
- `event`: This indicates the directionality of the event, from the perspective of the host system. INPUT events indicate data received from the student&#039;s terminal or client process. OUTPUT events indicate data being transmitted to the student or client.&lt;br /&gt;
&lt;br /&gt;
In the Python output, there are some derived values which are not recorded in the BPF probes, but calculated in the outer Python handler:&lt;br /&gt;
&lt;br /&gt;
- `pid` is derived from the upper 4 bytes of the combined `pidtgid` value, by shifting out the lower bytes.&lt;br /&gt;
&lt;br /&gt;
- `tgid` is derived by masking off the lower 4 bytes of the combined `pidtgid` value.&lt;br /&gt;
&lt;br /&gt;
- `time` is derived by adding the aforementioned clock offset calculation to the `rawtime` value.&lt;br /&gt;
&lt;br /&gt;
== Example Output ==&lt;br /&gt;
When &amp;lt;code&amp;gt;echo Hello World!\n&amp;lt;/code&amp;gt; was written to TTY, the following activity was captured:&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051966371111181 rawtime=203335230775 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051966372044241 rawtime=203336163835 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051966372190646 rawtime=203336310240 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051966372639326 rawtime=203336759469 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051968089522310 rawtime=205053641539 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968089690488 rawtime=205053809717 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051968089802828 rawtime=205053922397 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968089833388 rawtime=205053952388 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051968250835993 rawtime=205214954887 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968250966010 rawtime=205215084904 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051968251302359 rawtime=205215421253 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968251330720 rawtime=205215449614 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051969762481565 rawtime=206726601086 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051969762631118 rawtime=206726750639 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051969762777304 rawtime=206726896825 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051969762801534 rawtime=206726921161 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051970952290018 rawtime=207916408780 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051970952415054 rawtime=207916533816 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051970952582323 rawtime=207916701085 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051970952645255 rawtime=207916764825 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971611934058 rawtime=208576052862 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971612097568 rawtime=208576216372 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971612342263 rawtime=208576461926 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971612367333 rawtime=208576487354 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971808898991 rawtime=208773018069 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971809014928 rawtime=208773134006 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971809320248 rawtime=208773439326 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971809351426 rawtime=208773471241 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971964705058 rawtime=208928823985 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971964878073 rawtime=208928997000 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971965206444 rawtime=208929325371 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971965235901 rawtime=208929355554 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972143167788 rawtime=209107286648 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972143292895 rawtime=209107411755 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972143459449 rawtime=209107578309 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972143483528 rawtime=209107602911 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972318556514 rawtime=209282675286 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972318681585 rawtime=209282800357 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972318875590 rawtime=209282995496 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972318899197 rawtime=209283018165 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972587453662 rawtime=209551572401 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972587621515 rawtime=209551740254 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972587734382 rawtime=209551853121 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972587758332 rawtime=209551878383 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972700061714 rawtime=209664180622 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972700188164 rawtime=209664307072 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972700536831 rawtime=209664655739 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972700565465 rawtime=209664684373 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972892415567 rawtime=209856535138 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972892541864 rawtime=209856661435 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972892748515 rawtime=209856868086 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972892776412 rawtime=209856895983 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973053552503 rawtime=210017672160 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973053768028 rawtime=210017887685 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973053883021 rawtime=210018002678 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973053908007 rawtime=210018027638 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973140155837 rawtime=210104274616 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973140277309 rawtime=210104396088 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973140428835 rawtime=210104547614 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973140452038 rawtime=210104571622 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973250867779 rawtime=210214986547 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973250993810 rawtime=210215112578 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973251331050 rawtime=210215449818 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973251361348 rawtime=210215480116 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973335770189 rawtime=210299889755 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973335937186 rawtime=210300056752 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973336218966 rawtime=210300338532 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973336246835 rawtime=210300366528 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973665644437 rawtime=210629763107 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973665786687 rawtime=210629905357 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973666070698 rawtime=210630189368 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973666097902 rawtime=210630217539 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051974226180674 rawtime=211190299600 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226348069 rawtime=211190466995 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974226417647 rawtime=211190536573 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\n&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226440318 rawtime=211190559951 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=2&amp;gt;&lt;br /&gt;
 b&#039;\r\n&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974226501433 rawtime=211190620594 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=9&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004l\r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226556167 rawtime=211190675351 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=9&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004l\r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227307873 rawtime=211191426669 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=14&amp;gt;&lt;br /&gt;
 b&#039;Hello, World!\n&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227857480 rawtime=211191976447 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=8&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227952968 rawtime=211192071701 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=52&amp;gt;&lt;br /&gt;
 b&#039;\x1b]0;joe@bpf: ~\x07\x1b[01;32mjoe@bpf\x1b[00m:\x1b[01;34m~\x1b[00m$ &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974227997645 rawtime=211192116397 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=75&amp;gt;&lt;br /&gt;
 b&#039;Hello, World!\r\n\x1b[?2004h\x1b]0;joe@bpf: ~\x07\x1b[01;32mjoe@bpf\x1b[00m:\x1b[01;34m~\x1b[00m$ &#039;&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=885</id>
		<title>TTY Logging with BPF</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=885"/>
		<updated>2025-08-19T20:06:03Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Added some additional details that didn&amp;#039;t make it in before pages were frozen to deal with bots&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Demonstrations]]&lt;br /&gt;
See https://github.com/edurange/demo-bpf-tty-logger.&lt;br /&gt;
&lt;br /&gt;
Demonstrates how to capture TTY activity using BPF kernel probes.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
To run it one needs to have superuser privileges (for kernel access). The probes intercept all TTY activity on the host system - both inside and outside of containers. If the script is printing to a TTY device the prints themselves will also be observed, creating a feedback loop that will quickly consume the kernel buffers. As such the output should be redirected to a file. I recommend redirecting both STDOUT and STDERR as follows:&lt;br /&gt;
 sudo python3 [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] &amp;amp;&amp;gt; log&lt;br /&gt;
&lt;br /&gt;
== Explanation ==&lt;br /&gt;
[https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] is compact but there&#039;s a lot going on. Unlike [https://ttylog.sourceforge.net ttylog] and [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/analyze.py analyze.py], which it would replace, [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] does not rely on changing or proxying the TTY device itself. Rather, it utilizes [[wikipedia:Berkeley_Packet_Filter|Berkeley Packet Filters]], a kernel-level interface for hooking code into system calls; see also https://www.kernel.org/doc/html/latest/bpf/index.html for a specific implementation of the BPF interface. Instead of intercepting at the point of the TTY connection, we tamper with and tap the kernel calls that provide TTY services system-wide.&lt;br /&gt;
&lt;br /&gt;
=== Berkeley Packet Filter ===&lt;br /&gt;
BPF links compiled object code into the kernel. Newer extensions to BPF support using pre-compiled code payloads, but typically the code is loaded at runtime from C, with a tool such as [https://root.cern/cling/ cling]. It looks odd by Python standards, but the common practice is to embed a one-file C program as a string in the Python file, then send it to be compiled and linked in through the BPF API.&lt;br /&gt;
&lt;br /&gt;
The main area of interest are the functions injected into the kernel, called probes - kprobe__tty_write() and kprobe__n_tty_receive_buf_common(). The prefix &amp;quot;kprobe__&amp;quot; tells BPF to use these functions as probes automatically (but it&#039;s possible to use arbitrary functions, with an additional call to identify them.)&lt;br /&gt;
&lt;br /&gt;
tty_write() and tty_receive_buf_common() are used to copy data in and out of kernel memory, as user-land processes talk to the physical device drivers represented in software by the TTY resource. In its basic usage, BPF calls the probe with the same parameters that the system call received. We use this to read the data buffers as TTY devices transmit and receive.&lt;br /&gt;
&lt;br /&gt;
To safely permit alterations to the kernel, BPF enforces safety checks above and beyond normal C language requirements. As such, the kernel probe code may appear pedantic in the amount of guards used. These are necessary for approval by the BPF checker.&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
BPF lacks a wall clock time source. In other words, all of the time values available in the kernel under BPF are based on the system&#039;s uptime clock, not a time source synced to time of day. The uptime clocks have some unusual behavior compared to typical clocks. When the host system is halted or put to sleep, the clocks stop. From the perspective of software running on the host system, the system clocks move forward at a smooth rate, but the wall clock time jumps forward unpredictably whenever the system wakes from sleep.&lt;br /&gt;
&lt;br /&gt;
To account for this, first the raw time values must be captured as close to the actual TTY event as possible - preferably, as the first instruction in the probe. We note the system time as part of the record of the TTY event, which is then exfiltrated from the kernel using a shared memory buffer provided by BPF.&lt;br /&gt;
&lt;br /&gt;
In user space a handler function in the outer Python script reads events from the BPF buffer. There we have full access to wall clock time. Measuring the difference between system uptime and wall clock time is as simple as capturing both values, but it may occasionally jump as a result of changes to the offset value used to calibrate it - such as when the system receives a time update via network time protocol, which can occur quite frequently on modern operating systems.&lt;br /&gt;
&lt;br /&gt;
To watch for drift in the clock offset, we take the difference between the current system-wide wall clock time and the time extrapolated by adding our offset estimate to the most recent timestamp. If the drift between the two time sources exceeds some small threshhold, we calculate a new offset value. We also recalibrate the offset value on a regular interval, even if it doesn&#039;t exceed the drift limit. In our implementation we chose a drift threshold of one thousandth of a second, and a refresh timeout of one minute.&lt;br /&gt;
&lt;br /&gt;
The timing values are captured in a closure to avoid reliance on mutable global variables. calibratetimefactory() encloses the timing values with the method that updates them. API consumers need only call the resulting calibratetime() function to receive updated timing information, while being discouraged from tampering with the internal representation and underlying algorithm.&lt;br /&gt;
&lt;br /&gt;
=== Event Attributes ===&lt;br /&gt;
As mentioned, because this code runs in the kernel whenever the relevant system calls are invoked, it sees all TTY activity - from all processes and all users. Unlike ttylog, we are not attached to one particular TTY device. To distinguish between calls made by different services on behalf of different endpoints, we must record additional data about each system call event.&lt;br /&gt;
&lt;br /&gt;
In the order that they appear in the code, not necessarily by relevance:&lt;br /&gt;
&lt;br /&gt;
- `rawtime`: The raw value of the system uptime clock when the event was captured. Represented as nanoseconds of CPU runtime since boot up. A &amp;quot;monotonic clock&amp;quot; in hardware design terminology.&lt;br /&gt;
&lt;br /&gt;
- `cgid`: The &amp;quot;**C**ontrol **G**roup **ID**&amp;quot; (sometimes shortened &amp;quot;Cgroup&amp;quot;) is a Linux mechanism for grouping processes and other resources heirarchically. It can be used in some circumstances to identify processes as belonging to containers. Cgroups are a Linux kernel feature that do not have a direct analog on other POSIX systems, but so is BPF, so while I&#039;d like to stick to POSIX compatibility where possible that&#039;s just not relevant in this context.&lt;br /&gt;
&lt;br /&gt;
- `inode`: The &amp;quot;**i**ndex **node**&amp;quot; refers to the file-like object associated with the TTY device or psuedoterminal that is transmitting/receiving. This is a primary source of identifying information for our purposes, but there are some circumstances where it isn&#039;t available, and there are also cases where inode values will differ but we want to associate the data together anyways, such as when we see the same student log in on more than one terminal.&lt;br /&gt;
&lt;br /&gt;
- `pidtgid`: This encodes two values which come from BPF packed into a single variable - PID, the &amp;quot;**p**rocess **ID**&amp;quot; of the main thread, and TGID, the &amp;quot;**t**hread **g**roup **ID**&amp;quot;, which may contain a different ID for the current thread if the process has more than just a main thread.&lt;br /&gt;
&lt;br /&gt;
- `nsid`: This contains the &amp;quot;**n**ame**s**pace **ID**&amp;quot; of the calling process, which can help to identify containerized processes in some circumstances where CGID and PID/TGID leave ambiguity.&lt;br /&gt;
&lt;br /&gt;
- `comm`: This is the &amp;quot;**comm**and name&amp;quot;, a fixed-length 15-character identifier of the calling process. It is often not unique, and sometimes truncated and/or mangled, but may provide additional context in some situations and enhances the human readability of events.&lt;br /&gt;
&lt;br /&gt;
- `buf`: This is the &amp;quot;**buf**fer&amp;quot;. This is the C byte array that the kernel received from the caller, representing the data being communicated. It may be as long as a kernel page, which is 4kB on contemporary systems, and may or may not be null-terminated. The buffer contains raw bytes that have not been interpreted according to any text encoding, and in some cases the buffer will not be decodable by itself - multi-byte characters (like from Unicode) are not guaranteed to be complete and may be split between two buffer flushes. What this means is that text needs to be assembled and decoded at a higher level than we are working at while just capturing the data.&lt;br /&gt;
&lt;br /&gt;
- `len`: The number of bytes in the buffer. Not the same as the characters represented in the buffer. Definitely not the same as the number of characters that will show up on the terminal.&lt;br /&gt;
&lt;br /&gt;
- `event`: This indicates the directionality of the event, from the perspective of the host system. INPUT events indicate data received from the student&#039;s terminal or client process. OUTPUT events indicate data being transmitted to the student or client.&lt;br /&gt;
&lt;br /&gt;
In the Python output, there are some derived values which are not recorded in the BPF probes, but calculated in the outer Python handler:&lt;br /&gt;
&lt;br /&gt;
- `pid` is derived from the upper 4 bytes of the combined `pidtgid` value, by shifting out the lower bytes.&lt;br /&gt;
&lt;br /&gt;
- `tgid` is derived by masking off the lower 4 bytes of the combined `pidtgid` value.&lt;br /&gt;
&lt;br /&gt;
- `time` is derived by adding the aforementioned clock offset calculation to the `rawtime` value.&lt;br /&gt;
&lt;br /&gt;
== Example Output ==&lt;br /&gt;
When &amp;lt;code&amp;gt;echo Hello World!\n&amp;lt;/code&amp;gt; was written to TTY, the following activity was captured:&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051966371111181 rawtime=203335230775 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051966372044241 rawtime=203336163835 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051966372190646 rawtime=203336310240 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051966372639326 rawtime=203336759469 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051968089522310 rawtime=205053641539 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968089690488 rawtime=205053809717 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051968089802828 rawtime=205053922397 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968089833388 rawtime=205053952388 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051968250835993 rawtime=205214954887 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968250966010 rawtime=205215084904 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051968251302359 rawtime=205215421253 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968251330720 rawtime=205215449614 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051969762481565 rawtime=206726601086 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051969762631118 rawtime=206726750639 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051969762777304 rawtime=206726896825 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051969762801534 rawtime=206726921161 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051970952290018 rawtime=207916408780 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051970952415054 rawtime=207916533816 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051970952582323 rawtime=207916701085 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051970952645255 rawtime=207916764825 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971611934058 rawtime=208576052862 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971612097568 rawtime=208576216372 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971612342263 rawtime=208576461926 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971612367333 rawtime=208576487354 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971808898991 rawtime=208773018069 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971809014928 rawtime=208773134006 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971809320248 rawtime=208773439326 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971809351426 rawtime=208773471241 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971964705058 rawtime=208928823985 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971964878073 rawtime=208928997000 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971965206444 rawtime=208929325371 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971965235901 rawtime=208929355554 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972143167788 rawtime=209107286648 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972143292895 rawtime=209107411755 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972143459449 rawtime=209107578309 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972143483528 rawtime=209107602911 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972318556514 rawtime=209282675286 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972318681585 rawtime=209282800357 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972318875590 rawtime=209282995496 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972318899197 rawtime=209283018165 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972587453662 rawtime=209551572401 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972587621515 rawtime=209551740254 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972587734382 rawtime=209551853121 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972587758332 rawtime=209551878383 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972700061714 rawtime=209664180622 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972700188164 rawtime=209664307072 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972700536831 rawtime=209664655739 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972700565465 rawtime=209664684373 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972892415567 rawtime=209856535138 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972892541864 rawtime=209856661435 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972892748515 rawtime=209856868086 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972892776412 rawtime=209856895983 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973053552503 rawtime=210017672160 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973053768028 rawtime=210017887685 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973053883021 rawtime=210018002678 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973053908007 rawtime=210018027638 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973140155837 rawtime=210104274616 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973140277309 rawtime=210104396088 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973140428835 rawtime=210104547614 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973140452038 rawtime=210104571622 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973250867779 rawtime=210214986547 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973250993810 rawtime=210215112578 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973251331050 rawtime=210215449818 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973251361348 rawtime=210215480116 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973335770189 rawtime=210299889755 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973335937186 rawtime=210300056752 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973336218966 rawtime=210300338532 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973336246835 rawtime=210300366528 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973665644437 rawtime=210629763107 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973665786687 rawtime=210629905357 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973666070698 rawtime=210630189368 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973666097902 rawtime=210630217539 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051974226180674 rawtime=211190299600 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226348069 rawtime=211190466995 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974226417647 rawtime=211190536573 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\n&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226440318 rawtime=211190559951 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=2&amp;gt;&lt;br /&gt;
 b&#039;\r\n&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974226501433 rawtime=211190620594 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=9&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004l\r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226556167 rawtime=211190675351 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=9&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004l\r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227307873 rawtime=211191426669 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=14&amp;gt;&lt;br /&gt;
 b&#039;Hello, World!\n&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227857480 rawtime=211191976447 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=8&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227952968 rawtime=211192071701 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=52&amp;gt;&lt;br /&gt;
 b&#039;\x1b]0;joe@bpf: ~\x07\x1b[01;32mjoe@bpf\x1b[00m:\x1b[01;34m~\x1b[00m$ &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974227997645 rawtime=211192116397 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=75&amp;gt;&lt;br /&gt;
 b&#039;Hello, World!\r\n\x1b[?2004h\x1b]0;joe@bpf: ~\x07\x1b[01;32mjoe@bpf\x1b[00m:\x1b[01;34m~\x1b[00m$ &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051998831792273 rawtime=235795910526 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=869</id>
		<title>Category:Project History and Roadmaps</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=869"/>
		<updated>2025-07-11T23:26:33Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Instructions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a page to collect our history, accomplishments, needs, goals and wishlist items.&lt;br /&gt;
&lt;br /&gt;
The idea is to document all of the high-level material we&#039;ve produced, such as publications, major code releases and trial results. This collection can then be used as a timeline of our work and trajectory.&lt;br /&gt;
&lt;br /&gt;
As this content is developed we may want to adopt standards for how things are organized - particularly to distinguish between proposed goals, agreed-upon plans and retired items that are reference only.&lt;br /&gt;
&lt;br /&gt;
When making pages for a code release or academic paper it would be great to include working permalinks to the resource in question, especially full text for literature. A brief statement including additional details would also be helpful - such as who contributed to it and when, and a description of the state of the project at the time.&lt;br /&gt;
&lt;br /&gt;
Perhaps we could also include short biographical pages for contributors that care to share their information, but I&#039;ll wait to see what the group thinks of that before jumping in myself. ~Joe G&lt;br /&gt;
&lt;br /&gt;
== Project Timeline ==&lt;br /&gt;
This list may not stay accurate as it grows. Verify any inferences with human sources.&lt;br /&gt;
&lt;br /&gt;
* [[The Conception of EDURange]] [2011]: Conceptually, EDURange started around 2011 when Jens, Michael Locasto, and Richard started talking about creating exercises for cybersecurity courses. The idea was generated at a dinner with Michael, Sergey Bratus, Brian Fite, and Richard. Brian was packet master for a competition called PacketWars, and he was looking for a way to be a player and not the one running the competition. ... - Richard&lt;br /&gt;
== Instructions ==&lt;br /&gt;
Do not write individual items here; this page is just for indexing and coordinating the entries under this category.&lt;br /&gt;
&lt;br /&gt;
* First create a page with a title appropriate for your item. There&#039;s no hard convention yet, but strive for readability/searchability.&lt;br /&gt;
* In the source of that page, add the following on the first line: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Category:Project History and Roadmap]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Your page will be automatically indexed into this category. You can also add an entry in the timeline below.&lt;br /&gt;
&lt;br /&gt;
=== Page contents ===&lt;br /&gt;
Please include context for your items, as future contributors may use these accounts for research. Readers should not need to rely on edit history to determine the date and author. At a minimum, the page should include:&lt;br /&gt;
&lt;br /&gt;
* Your identity as the writer.&lt;br /&gt;
* The date of the original post.&lt;br /&gt;
* The timespan, if the post refers to something that has already happened or has a concrete goal date.&lt;br /&gt;
&lt;br /&gt;
=== Timeline entries ===&lt;br /&gt;
Please try to keep timeline entries to a brief paragraph. Include the name of the page, the time in question, and your name as author.&lt;br /&gt;
&lt;br /&gt;
Do not add future items to this main timeline. Future goals that don&#039;t come to pass may need to be edited after the fact to avoid confusing readers - let&#039;s put such content in a dedicated place where it doesn&#039;t clutter up more reliable information.&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=868</id>
		<title>Category:Project History and Roadmaps</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=868"/>
		<updated>2025-07-11T23:25:02Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a page to collect our history, accomplishments, needs, goals and wishlist items.&lt;br /&gt;
&lt;br /&gt;
The idea is to document all of the high-level material we&#039;ve produced, such as publications, major code releases and trial results. This collection can then be used as a timeline of our work and trajectory.&lt;br /&gt;
&lt;br /&gt;
As this content is developed we may want to adopt standards for how things are organized - particularly to distinguish between proposed goals, agreed-upon plans and retired items that are reference only.&lt;br /&gt;
&lt;br /&gt;
When making pages for a code release or academic paper it would be great to include working permalinks to the resource in question, especially full text for literature. A brief statement including additional details would also be helpful - such as who contributed to it and when, and a description of the state of the project at the time.&lt;br /&gt;
&lt;br /&gt;
Perhaps we could also include short biographical pages for contributors that care to share their information, but I&#039;ll wait to see what the group thinks of that before jumping in myself. ~Joe G&lt;br /&gt;
&lt;br /&gt;
== Project Timeline ==&lt;br /&gt;
This list may not stay accurate as it grows. Verify any inferences with human sources.&lt;br /&gt;
&lt;br /&gt;
* [[The Conception of EDURange]] [2011]: Conceptually, EDURange started around 2011 when Jens, Michael Locasto, and Richard started talking about creating exercises for cybersecurity courses. The idea was generated at a dinner with Michael, Sergey Bratus, Brian Fite, and Richard. Brian was packet master for a competition called PacketWars, and he was looking for a way to be a player and not the one running the competition. ... - Richard&lt;br /&gt;
== Instructions ==&lt;br /&gt;
Do not write individual items here; this page is just for indexing and coordinating the entries under this category.&lt;br /&gt;
&lt;br /&gt;
* First create a page with a title appropriate for your item. There&#039;s no hard convention yet, but strive for readability/searchability.&lt;br /&gt;
* In the source of that page, add the following on the first line: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Category:Project History and Roadmap]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Your page will be automatically indexed into the category. You can also add an entry in the timeline below.&lt;br /&gt;
&lt;br /&gt;
=== Page contents ===&lt;br /&gt;
Please include context for your items, as future contributors may use these accounts for research. Readers should not need to rely on edit history to determine the date and author. At a minimum, the page should include:&lt;br /&gt;
&lt;br /&gt;
* Your identity as the writer.&lt;br /&gt;
* The date of the original post.&lt;br /&gt;
* The timespan, if the post refers to something that has already happened or has a concrete goal date.&lt;br /&gt;
&lt;br /&gt;
=== Timeline entries ===&lt;br /&gt;
Please try to keep timeline entries to a brief paragraph. Include the name of the page, the time in question, and your name as author.&lt;br /&gt;
&lt;br /&gt;
Do not add future items to this main timeline. Future goals that don&#039;t come to pass may need to be edited after the fact to avoid confusing readers - let&#039;s put such content in a dedicated place where it doesn&#039;t clutter up more reliable information.&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=862</id>
		<title>TTY Logging with BPF</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=862"/>
		<updated>2025-06-30T20:22:34Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Demonstrations]]&lt;br /&gt;
See https://github.com/edurange/demo-bpf-tty-logger.&lt;br /&gt;
&lt;br /&gt;
Demonstrates how to capture TTY activity using BPF kernel probes.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
To run it one needs to have superuser privileges (for kernel access). The probes intercept all TTY activity on the host system - both inside and outside of containers. If the script is printing to a TTY device the prints themselves will also be observed, creating a feedback loop that will quickly consume the kernel buffers. As such the output should be redirected to a file. I recommend redirecting both STDOUT and STDERR as follows:&lt;br /&gt;
 sudo python3 [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] &amp;amp;&amp;gt; log&lt;br /&gt;
&lt;br /&gt;
== Explanation ==&lt;br /&gt;
[https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] is compact but there&#039;s a lot going on. Unlike [https://ttylog.sourceforge.net ttylog] and [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/analyze.py analyze.py], which it would replace, [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] does not rely on changing or proxying the TTY device itself. Rather, it utilizes [[wikipedia:Berkeley_Packet_Filter|Berkeley Packet Filters]], a kernel-level interface for hooking code into system calls; see also https://www.kernel.org/doc/html/latest/bpf/index.html for a specific implementation of the BPF interface. Instead of intercepting at the point of the TTY connection, we tamper with and tap the kernel calls that provide TTY services system-wide.&lt;br /&gt;
&lt;br /&gt;
=== Berkeley Packet Filter ===&lt;br /&gt;
BPF links compiled object code into the kernel. Newer extensions to BPF support using pre-compiled code payloads, but typically the code is loaded at runtime from C, with a tool such as [https://root.cern/cling/ cling]. It looks odd by Python standards, but the common practice is to embed a one-file C program as a string in the Python file, then send it to be compiled and linked in through the BPF API.&lt;br /&gt;
&lt;br /&gt;
The main area of interest are the functions injected into the kernel, called probes - kprobe__tty_write() and kprobe__n_tty_receive_buf_common(). The prefix &amp;quot;kprobe__&amp;quot; tells BPF to use these functions as probes automatically (but it&#039;s possible to use arbitrary functions, with an additional call to identify them.)&lt;br /&gt;
&lt;br /&gt;
tty_write() and tty_receive_buf_common() are used to copy data in and out of kernel memory, as user-land processes talk to the physical device drivers represented in software by the TTY resource. In its basic usage, BPF calls the probe with the same parameters that the system call received. We use this to read the data buffers as TTY devices transmit and receive.&lt;br /&gt;
&lt;br /&gt;
To safely permit alterations to the kernel, BPF enforces safety checks above and beyond normal C language requirements. As such, the kernel probe code may appear pedantic in the amount of guards used. These are necessary for approval by the BPF checker.&lt;br /&gt;
&lt;br /&gt;
=== Timing ===&lt;br /&gt;
BPF lacks a wall clock time source. In other words, all of the time values available in the kernel under BPF are based on the system&#039;s uptime clock, not a time source synced to time of day. The uptime clocks have some unusual behavior compared to typical clocks. When the host system is halted or put to sleep, the clocks stop. From the perspective of software running on the host system, the system clocks move forward at a smooth rate, but the wall clock time jumps forward unpredictably whenever the system wakes from sleep.&lt;br /&gt;
&lt;br /&gt;
To account for this, first the raw time values must be captured as close to the actual TTY event as possible - preferably, as the first instruction in the probe. We note the system time as part of the record of the TTY event, which is then exfiltrated from the kernel using a shared memory buffer provided by BPF.&lt;br /&gt;
&lt;br /&gt;
In Python, a handler function reads events out of the buffer. In user space we have full access to wall clock time. Measuring the difference between system uptime and wall clock time is simple, but it may jump as a result of changes to the offset value used to calibrate it - such as when the system receives a time update via NTP&lt;br /&gt;
&lt;br /&gt;
== Example Output ==&lt;br /&gt;
When &amp;lt;code&amp;gt;echo Hello World!\n&amp;lt;/code&amp;gt; was written to TTY, the following activity was captured:&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051966371111181 rawtime=203335230775 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051966372044241 rawtime=203336163835 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051966372190646 rawtime=203336310240 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051966372639326 rawtime=203336759469 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051968089522310 rawtime=205053641539 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968089690488 rawtime=205053809717 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051968089802828 rawtime=205053922397 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968089833388 rawtime=205053952388 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051968250835993 rawtime=205214954887 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968250966010 rawtime=205215084904 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051968251302359 rawtime=205215421253 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968251330720 rawtime=205215449614 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051969762481565 rawtime=206726601086 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051969762631118 rawtime=206726750639 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051969762777304 rawtime=206726896825 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051969762801534 rawtime=206726921161 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051970952290018 rawtime=207916408780 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051970952415054 rawtime=207916533816 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051970952582323 rawtime=207916701085 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051970952645255 rawtime=207916764825 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971611934058 rawtime=208576052862 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971612097568 rawtime=208576216372 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971612342263 rawtime=208576461926 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971612367333 rawtime=208576487354 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971808898991 rawtime=208773018069 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971809014928 rawtime=208773134006 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971809320248 rawtime=208773439326 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971809351426 rawtime=208773471241 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971964705058 rawtime=208928823985 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971964878073 rawtime=208928997000 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971965206444 rawtime=208929325371 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971965235901 rawtime=208929355554 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972143167788 rawtime=209107286648 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972143292895 rawtime=209107411755 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972143459449 rawtime=209107578309 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972143483528 rawtime=209107602911 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972318556514 rawtime=209282675286 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972318681585 rawtime=209282800357 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972318875590 rawtime=209282995496 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972318899197 rawtime=209283018165 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972587453662 rawtime=209551572401 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972587621515 rawtime=209551740254 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972587734382 rawtime=209551853121 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972587758332 rawtime=209551878383 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972700061714 rawtime=209664180622 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972700188164 rawtime=209664307072 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972700536831 rawtime=209664655739 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972700565465 rawtime=209664684373 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972892415567 rawtime=209856535138 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972892541864 rawtime=209856661435 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972892748515 rawtime=209856868086 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972892776412 rawtime=209856895983 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973053552503 rawtime=210017672160 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973053768028 rawtime=210017887685 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973053883021 rawtime=210018002678 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973053908007 rawtime=210018027638 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973140155837 rawtime=210104274616 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973140277309 rawtime=210104396088 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973140428835 rawtime=210104547614 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973140452038 rawtime=210104571622 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973250867779 rawtime=210214986547 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973250993810 rawtime=210215112578 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973251331050 rawtime=210215449818 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973251361348 rawtime=210215480116 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973335770189 rawtime=210299889755 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973335937186 rawtime=210300056752 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973336218966 rawtime=210300338532 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973336246835 rawtime=210300366528 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973665644437 rawtime=210629763107 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973665786687 rawtime=210629905357 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973666070698 rawtime=210630189368 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973666097902 rawtime=210630217539 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051974226180674 rawtime=211190299600 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226348069 rawtime=211190466995 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974226417647 rawtime=211190536573 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\n&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226440318 rawtime=211190559951 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=2&amp;gt;&lt;br /&gt;
 b&#039;\r\n&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974226501433 rawtime=211190620594 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=9&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004l\r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226556167 rawtime=211190675351 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=9&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004l\r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227307873 rawtime=211191426669 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=14&amp;gt;&lt;br /&gt;
 b&#039;Hello, World!\n&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227857480 rawtime=211191976447 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=8&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227952968 rawtime=211192071701 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=52&amp;gt;&lt;br /&gt;
 b&#039;\x1b]0;joe@bpf: ~\x07\x1b[01;32mjoe@bpf\x1b[00m:\x1b[01;34m~\x1b[00m$ &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974227997645 rawtime=211192116397 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=75&amp;gt;&lt;br /&gt;
 b&#039;Hello, World!\r\n\x1b[?2004h\x1b]0;joe@bpf: ~\x07\x1b[01;32mjoe@bpf\x1b[00m:\x1b[01;34m~\x1b[00m$ &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051998831792273 rawtime=235795910526 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=851</id>
		<title>TTY Logging with BPF</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=851"/>
		<updated>2025-06-30T19:21:52Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Demonstrations]]&lt;br /&gt;
See https://github.com/edurange/demo-bpf-tty-logger.&lt;br /&gt;
&lt;br /&gt;
Demonstrates how to capture TTY activity using BPF kernel probes.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
To run it one needs to have superuser privileges (for kernel access). The probes intercept all TTY activity on the host system - both inside and outside of containers. If the script is printing to a TTY device the prints themselves will also be observed, creating a feedback loop that will quickly consume the kernel buffers. As such the output should be redirected to a file. I recommend redirecting both STDOUT and STDERR as follows:&lt;br /&gt;
 sudo python3 [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] &amp;amp;&amp;gt; log&lt;br /&gt;
&lt;br /&gt;
== Explanation ==&lt;br /&gt;
[https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] is compact but there&#039;s a lot going on. Unlike [https://ttylog.sourceforge.net ttylog] and [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/analyze.py analyze.py], which it would replace, [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] does not rely on changing or proxying the TTY device itself. Rather, it utilizes [[wikipedia:Berkeley_Packet_Filter|Berkeley Packet Filters]], a kernel-level interface for hooking code into system calls; see also https://www.kernel.org/doc/html/latest/bpf/index.html for a specific implementation of the BPF interface. Instead of intercepting at the point of the TTY connection, we tamper with and tap the kernel calls that provide TTY services system-wide.&lt;br /&gt;
&lt;br /&gt;
=== Berkeley Packet Filter ===&lt;br /&gt;
BPF links compiled object code into the kernel. Newer extensions to BPF support using pre-compiled code payloads, but typically the code is loaded at runtime from C, with a tool such as [https://root.cern/cling/ cling]. It looks odd by Python standards, but the common practice is to embed a one-file C program as a string in the Python file, then send it to be compiled and linked in through the BPF API.&lt;br /&gt;
&lt;br /&gt;
The main area of interest are the functions injected into the kernel, called probes - kprobe__tty_write() and kprobe__n_tty_receive_buf_common(). The prefix &amp;quot;kprobe__&amp;quot; tells BPF to use these functions as probes automatically (but it&#039;s possible to use arbitrary functions, with an additional call to identify them.)&lt;br /&gt;
&lt;br /&gt;
tty_write() and tty_receive_buf_common() are used to copy data in and out of kernel memory, as user-land processes talk to the physical device drivers represented in software by the TTY resource. In its basic usage, BPF calls the probe with the same parameters that the system call received. We use this to read the data buffers as TTY devices transmit and receive.&lt;br /&gt;
&lt;br /&gt;
== Example Output ==&lt;br /&gt;
When &amp;lt;code&amp;gt;echo Hello World!\n&amp;lt;/code&amp;gt; is written to TTY, the following activity is captured:&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051966371111181 rawtime=203335230775 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051966372044241 rawtime=203336163835 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051966372190646 rawtime=203336310240 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051966372639326 rawtime=203336759469 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051968089522310 rawtime=205053641539 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968089690488 rawtime=205053809717 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051968089802828 rawtime=205053922397 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968089833388 rawtime=205053952388 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;c&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051968250835993 rawtime=205214954887 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968250966010 rawtime=205215084904 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051968251302359 rawtime=205215421253 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051968251330720 rawtime=205215449614 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051969762481565 rawtime=206726601086 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051969762631118 rawtime=206726750639 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051969762777304 rawtime=206726896825 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051969762801534 rawtime=206726921161 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051970952290018 rawtime=207916408780 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051970952415054 rawtime=207916533816 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051970952582323 rawtime=207916701085 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051970952645255 rawtime=207916764825 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971611934058 rawtime=208576052862 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971612097568 rawtime=208576216372 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971612342263 rawtime=208576461926 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971612367333 rawtime=208576487354 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;H&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971808898991 rawtime=208773018069 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971809014928 rawtime=208773134006 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971809320248 rawtime=208773439326 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971809351426 rawtime=208773471241 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;e&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051971964705058 rawtime=208928823985 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971964878073 rawtime=208928997000 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051971965206444 rawtime=208929325371 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051971965235901 rawtime=208929355554 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972143167788 rawtime=209107286648 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972143292895 rawtime=209107411755 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972143459449 rawtime=209107578309 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972143483528 rawtime=209107602911 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972318556514 rawtime=209282675286 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972318681585 rawtime=209282800357 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972318875590 rawtime=209282995496 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972318899197 rawtime=209283018165 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972587453662 rawtime=209551572401 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972587621515 rawtime=209551740254 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972587734382 rawtime=209551853121 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972587758332 rawtime=209551878383 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;,&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972700061714 rawtime=209664180622 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972700188164 rawtime=209664307072 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972700536831 rawtime=209664655739 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972700565465 rawtime=209664684373 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039; &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051972892415567 rawtime=209856535138 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972892541864 rawtime=209856661435 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051972892748515 rawtime=209856868086 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051972892776412 rawtime=209856895983 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;W&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973053552503 rawtime=210017672160 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973053768028 rawtime=210017887685 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973053883021 rawtime=210018002678 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973053908007 rawtime=210018027638 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;o&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973140155837 rawtime=210104274616 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973140277309 rawtime=210104396088 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973140428835 rawtime=210104547614 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973140452038 rawtime=210104571622 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973250867779 rawtime=210214986547 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973250993810 rawtime=210215112578 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973251331050 rawtime=210215449818 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973251361348 rawtime=210215480116 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;l&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973335770189 rawtime=210299889755 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973335937186 rawtime=210300056752 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973336218966 rawtime=210300338532 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973336246835 rawtime=210300366528 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;d&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051973665644437 rawtime=210629763107 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973665786687 rawtime=210629905357 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051973666070698 rawtime=210630189368 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051973666097902 rawtime=210630217539 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;!&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051974226180674 rawtime=211190299600 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226348069 rawtime=211190466995 cgid=1 inode=0 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974226417647 rawtime=211190536573 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=1&amp;gt;&lt;br /&gt;
 b&#039;\n&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226440318 rawtime=211190559951 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=2&amp;gt;&lt;br /&gt;
 b&#039;\r\n&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974226501433 rawtime=211190620594 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=9&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004l\r&#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974226556167 rawtime=211190675351 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=9&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004l\r&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227307873 rawtime=211191426669 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=14&amp;gt;&lt;br /&gt;
 b&#039;Hello, World!\n&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227857480 rawtime=211191976447 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=8&amp;gt;&lt;br /&gt;
 b&#039;\x1b[?2004h&#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2580 tid=2580 time=1751051974227952968 rawtime=211192071701 cgid=7827 inode=3 pidtgid=11081015626260 nsid=12616466428 comm=b&#039;bash&#039; len=52&amp;gt;&lt;br /&gt;
 b&#039;\x1b]0;joe@bpf: ~\x07\x1b[01;32mjoe@bpf\x1b[00m:\x1b[01;34m~\x1b[00m$ &#039;&lt;br /&gt;
 &amp;lt;OUTPUT pid=67 tid=67 time=1751051974227997645 rawtime=211192116397 cgid=1 inode=7863412966886368629 pidtgid=287762808899 nsid=12616466428 comm=b&#039;kworker/u10:5&#039; len=75&amp;gt;&lt;br /&gt;
 b&#039;Hello, World!\r\n\x1b[?2004h\x1b]0;joe@bpf: ~\x07\x1b[01;32mjoe@bpf\x1b[00m:\x1b[01;34m~\x1b[00m$ &#039;&lt;br /&gt;
 &amp;lt;INPUT pid=2579 tid=2579 time=1751051998831792273 rawtime=235795910526 cgid=7827 inode=89 pidtgid=11076720658963 nsid=12616466428 comm=b&#039;sshd&#039; len=1&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=832</id>
		<title>Category:Project History and Roadmaps</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=832"/>
		<updated>2025-06-30T17:15:09Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Project Timeline */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a page to collect our history, accomplishments, needs, goals and wishlist items.&lt;br /&gt;
&lt;br /&gt;
The idea is to document all of the high-level material we&#039;ve produced, such as publications, major code releases and trial results. This collection can then be used as a timeline of our work and trajectory.&lt;br /&gt;
&lt;br /&gt;
As this content is developed we may want to adopt standards for how things are organized - particularly to distinguish between proposed goals, agreed-upon plans and retired items that are reference only.&lt;br /&gt;
&lt;br /&gt;
When making pages for a code release or academic paper it would be great to include working permalinks to the resource in question, especially full text for literature. A brief statement including additional details would also be helpful - such as who contributed to it and when, and a description of the state of the project at the time.&lt;br /&gt;
&lt;br /&gt;
Perhaps we could also include short biographical pages for contributors that care to share their information, but I&#039;ll wait to see what the group thinks of that before jumping in myself. ~Joe G&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
Do not write individual items here; this page is just for indexing and coordinating the entries under this category.&lt;br /&gt;
&lt;br /&gt;
* First create a page with a title appropriate for your item. There&#039;s no hard convention yet, but strive for readability/searchability.&lt;br /&gt;
* In the source of that page, add the following on the first line: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Category:Project History and Roadmap]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Your page will be automatically indexed into the category. You can also add an entry in the timeline below.&lt;br /&gt;
&lt;br /&gt;
=== Page contents ===&lt;br /&gt;
Please include context for your items, as future contributors may use these accounts for research. Readers should not need to rely on edit history to determine the date and author. At a minimum, the page should include:&lt;br /&gt;
&lt;br /&gt;
* Your identity as the writer.&lt;br /&gt;
* The date of the original post.&lt;br /&gt;
* The timespan, if the post refers to something that has already happened or has a concrete goal date.&lt;br /&gt;
&lt;br /&gt;
=== Timeline entries ===&lt;br /&gt;
Please try to keep timeline entries to a brief paragraph. Include the name of the page, the time in question, and your name as author.&lt;br /&gt;
&lt;br /&gt;
Do not add future items to this main timeline. Future goals that don&#039;t come to pass may need to be edited after the fact to avoid confusing readers - let&#039;s put such content in a dedicated place where it doesn&#039;t clutter up more reliable information.&lt;br /&gt;
&lt;br /&gt;
== Project Timeline ==&lt;br /&gt;
This list may not stay accurate as it grows. Verify any inferences with human sources.&lt;br /&gt;
&lt;br /&gt;
* [[The Conception of EDURange]] [2011]: Conceptually, EDURange started around 2011 when Jens, Michael Locasto, and Richard started talking about creating exercises for cybersecurity courses. The idea was generated at a dinner with Michael, Sergey Bratus, Brian Fite, and Richard. Brian was packet master for a competition called PacketWars, and he was looking for a way to be a player and not the one running the competition. ... - Richard&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=831</id>
		<title>Category:Project History and Roadmaps</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=831"/>
		<updated>2025-06-30T17:14:41Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Timeline entries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a page to collect our history, accomplishments, needs, goals and wishlist items.&lt;br /&gt;
&lt;br /&gt;
The idea is to document all of the high-level material we&#039;ve produced, such as publications, major code releases and trial results. This collection can then be used as a timeline of our work and trajectory.&lt;br /&gt;
&lt;br /&gt;
As this content is developed we may want to adopt standards for how things are organized - particularly to distinguish between proposed goals, agreed-upon plans and retired items that are reference only.&lt;br /&gt;
&lt;br /&gt;
When making pages for a code release or academic paper it would be great to include working permalinks to the resource in question, especially full text for literature. A brief statement including additional details would also be helpful - such as who contributed to it and when, and a description of the state of the project at the time.&lt;br /&gt;
&lt;br /&gt;
Perhaps we could also include short biographical pages for contributors that care to share their information, but I&#039;ll wait to see what the group thinks of that before jumping in myself. ~Joe G&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
Do not write individual items here; this page is just for indexing and coordinating the entries under this category.&lt;br /&gt;
&lt;br /&gt;
* First create a page with a title appropriate for your item. There&#039;s no hard convention yet, but strive for readability/searchability.&lt;br /&gt;
* In the source of that page, add the following on the first line: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Category:Project History and Roadmap]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Your page will be automatically indexed into the category. You can also add an entry in the timeline below.&lt;br /&gt;
&lt;br /&gt;
=== Page contents ===&lt;br /&gt;
Please include context for your items, as future contributors may use these accounts for research. Readers should not need to rely on edit history to determine the date and author. At a minimum, the page should include:&lt;br /&gt;
&lt;br /&gt;
* Your identity as the writer.&lt;br /&gt;
* The date of the original post.&lt;br /&gt;
* The timespan, if the post refers to something that has already happened or has a concrete goal date.&lt;br /&gt;
&lt;br /&gt;
=== Timeline entries ===&lt;br /&gt;
Please try to keep timeline entries to a brief paragraph. Include the name of the page, the time in question, and your name as author.&lt;br /&gt;
&lt;br /&gt;
Do not add future items to this main timeline. Future goals that don&#039;t come to pass may need to be edited after the fact to avoid confusing readers - let&#039;s put such content in a dedicated place where it doesn&#039;t clutter up more reliable information.&lt;br /&gt;
&lt;br /&gt;
== Project Timeline ==&lt;br /&gt;
This list may not stay accurate as it grows. Verify any inferences with human sources.&lt;br /&gt;
&lt;br /&gt;
* [[The Conception of EDURange]] [time?]: Conceptually, EDURange started around 2011 when Jens, Michael Locasto, and Richard started talking about creating exercises for cybersecurity courses. The idea was generated at a dinner with Michael, Sergey Bratus, Brian Fite, and Richard. Brian was packet master for a competition called PacketWars, and he was looking for a way to be a player and not the one running the competition. ... - Richard&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=830</id>
		<title>Category:Project History and Roadmaps</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=830"/>
		<updated>2025-06-30T17:12:17Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Added instructions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a page to collect our history, accomplishments, needs, goals and wishlist items.&lt;br /&gt;
&lt;br /&gt;
The idea is to document all of the high-level material we&#039;ve produced, such as publications, major code releases and trial results. This collection can then be used as a timeline of our work and trajectory.&lt;br /&gt;
&lt;br /&gt;
As this content is developed we may want to adopt standards for how things are organized - particularly to distinguish between proposed goals, agreed-upon plans and retired items that are reference only.&lt;br /&gt;
&lt;br /&gt;
When making pages for a code release or academic paper it would be great to include working permalinks to the resource in question, especially full text for literature. A brief statement including additional details would also be helpful - such as who contributed to it and when, and a description of the state of the project at the time.&lt;br /&gt;
&lt;br /&gt;
Perhaps we could also include short biographical pages for contributors that care to share their information, but I&#039;ll wait to see what the group thinks of that before jumping in myself. ~Joe G&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
Do not write individual items here; this page is just for indexing and coordinating the entries under this category.&lt;br /&gt;
&lt;br /&gt;
* First create a page with a title appropriate for your item. There&#039;s no hard convention yet, but strive for readability/searchability.&lt;br /&gt;
* In the source of that page, add the following on the first line: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;[[Category:Project History and Roadmap]]&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Your page will be automatically indexed into the category. You can also add an entry in the timeline below.&lt;br /&gt;
&lt;br /&gt;
=== Page contents ===&lt;br /&gt;
Please include context for your items, as future contributors may use these accounts for research. Readers should not need to rely on edit history to determine the date and author. At a minimum, the page should include:&lt;br /&gt;
&lt;br /&gt;
* Your identity as the writer.&lt;br /&gt;
* The date of the original post.&lt;br /&gt;
* The timespan, if the post refers to something that has already happened or has a concrete goal date.&lt;br /&gt;
&lt;br /&gt;
=== Timeline entries ===&lt;br /&gt;
Do not add future items to this main timeline. Future goals that don&#039;t come to pass may need to be edited after the fact to avoid confusing readers - let&#039;s put such content in a dedicated place where it doesn&#039;t clutter up more reliable information.&lt;br /&gt;
&lt;br /&gt;
Please try to keep timeline entries to a brief paragraph. Include the name of the page, the time in question, and your name as author.&lt;br /&gt;
&lt;br /&gt;
== Project Timeline ==&lt;br /&gt;
This list may not stay accurate as it grows. Verify any inferences with human sources.&lt;br /&gt;
&lt;br /&gt;
* [[The Conception of EDURange]] [time?]: Conceptually, EDURange started around 2011 when Jens, Michael Locasto, and Richard started talking about creating exercises for cybersecurity courses. The idea was generated at a dinner with Michael, Sergey Bratus, Brian Fite, and Richard. Brian was packet master for a competition called PacketWars, and he was looking for a way to be a player and not the one running the competition. ... - Richard&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=The_Conception_of_EDURange&amp;diff=827</id>
		<title>The Conception of EDURange</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=The_Conception_of_EDURange&amp;diff=827"/>
		<updated>2025-06-30T16:43:35Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Project History and Roadmaps]]&lt;br /&gt;
&lt;br /&gt;
Conceptually, EDURange started around 2011 when Jens, Michael Locasto, and Richard started talking about creating exercises for cybersecurity courses. The idea was generated at a dinner with Michael, Sergey Bratus, Brian Fite, and Richard. Brian was packet master for a competition called PacketWars, and he was looking for a way to be a player and not the one running the competition. He had a number of innovative ideas. He wanted a way to specify competition environments, so that they could be replicated in different frameworks and they would be comparable, i.e. a standardization methodology for attack-defense competitions. &lt;br /&gt;
&lt;br /&gt;
Michael was interested in the question of what makes a great cybersecurity expert. Someone who not only knows the tools but also how to apply them in innovative ways. For Michael, this was captured by the concept of analysis skills. It is the ability to see patterns in large complex data or systems. There were only a few frameworks available at the time: SEED labs, The Rave, and DeterLab. In our view, their exercises did not emphasize analysis, and the problem was that we could not modify them to create ones that did. A vision we had was that analysis takes time and doesn’t fit into a 2 hour slot. Sometimes you need to think about a problem for days before a breakthrough happens. Our idea was that you needed repeatable exercises that students could come back to. The closest we have come to that is the last challenge in SSH Inception, where as soon as bash runs, it logs the user out. The tension is that students want something that they can complete in a fixed short amount of time. Perhaps we need that for introductory exercises but can move away from that in the more advanced ones. Also, there are different ways to implement such an open-ended approach. It could be that the scenario can be suspended and re-started, or there would be multiple levels within the scenario, or there would be multiple versions of the scenario that require the same type of analysis.&lt;br /&gt;
&lt;br /&gt;
- Richard&lt;br /&gt;
&lt;br /&gt;
2025-06-29&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=824</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=824"/>
		<updated>2025-06-30T16:35:57Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Developer Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the EDURange Wiki. This is less of a formal documentation as it is a living document.&lt;br /&gt;
&lt;br /&gt;
I think that if it&#039;s a choice between losing track of people&#039;s contributions and having a messy wiki, I&#039;d much prefer a messy wiki.  It&#039;s my hope that we can gather all of our notes, thoughts, and loosely related ephemera here, rather than having it scattered across correspondence and various sharing platforms.&lt;br /&gt;
&lt;br /&gt;
We don&#039;t have many conventions yet. Please follow the Golden Rule and treat others as you would be treated. Put your name on your changes. Consider posting to the discussion tab or appending to a page rather than overwriting it. Try not to overwrite the personal work of others.&lt;br /&gt;
&lt;br /&gt;
If it&#039;s installable/runnable/code of any sort, put it on GitHub as well - preferably under the edurange organization so that our future contributors will have seamless access to it too.&lt;br /&gt;
&lt;br /&gt;
Thanks for your time.&lt;br /&gt;
&lt;br /&gt;
~Joe G&lt;br /&gt;
&lt;br /&gt;
== The EDURange Project ==&lt;br /&gt;
[[:Category:Project History and Roadmaps|Project History and Roadmaps]]&lt;br /&gt;
&lt;br /&gt;
== Developer Links ==&lt;br /&gt;
[[Style Guidelines and Developer Tools]]&lt;br /&gt;
&lt;br /&gt;
[[Reference Materials]]&lt;br /&gt;
&lt;br /&gt;
[[:Category:Demonstrations|Demonstrations]]&lt;br /&gt;
&lt;br /&gt;
[[Design Stories (OLD)]]&lt;br /&gt;
&lt;br /&gt;
[[Interface Design]]&lt;br /&gt;
&lt;br /&gt;
[[Scenario Creation Guide]]&lt;br /&gt;
&lt;br /&gt;
[[Terraform Design]]&lt;br /&gt;
&lt;br /&gt;
[[Hosting Requirements]]&lt;br /&gt;
&lt;br /&gt;
[[Domain Modeling]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We&#039;re still figuring out Media Wiki, so I kept the following...&lt;br /&gt;
&lt;br /&gt;
== Orphaned Default Media Wiki Content ==&lt;br /&gt;
&amp;lt;strong&amp;gt;Welcome to the EDURange Wiki&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Consult the [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents User&#039;s Guide] for information on using the wiki software.&lt;br /&gt;
&lt;br /&gt;
== Getting started with Media Wiki ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Configuration settings list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]&lt;br /&gt;
* [https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/ MediaWiki release mailing list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=823</id>
		<title>Category:Project History and Roadmaps</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Category:Project_History_and_Roadmaps&amp;diff=823"/>
		<updated>2025-06-30T16:34:17Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Created page with &amp;quot;This is a page to collect our history, accomplishments, needs, goals and wishlist items.  The idea is to document all of the high-level material we&amp;#039;ve produced, such as publications, major code releases and trial results. This collection can then be used as a timeline of our work and trajectory.  As this content is developed we may want to adopt standards for how things are organized - particularly to distinguish between proposed goals, agreed-upon plans and retired item...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a page to collect our history, accomplishments, needs, goals and wishlist items.&lt;br /&gt;
&lt;br /&gt;
The idea is to document all of the high-level material we&#039;ve produced, such as publications, major code releases and trial results. This collection can then be used as a timeline of our work and trajectory.&lt;br /&gt;
&lt;br /&gt;
As this content is developed we may want to adopt standards for how things are organized - particularly to distinguish between proposed goals, agreed-upon plans and retired items that are reference only.&lt;br /&gt;
&lt;br /&gt;
When making pages for a code release or academic paper it would be great to include working permalinks to the resource in question, especially full text for literature. A brief statement including additional details would also be helpful - such as who contributed to it and when, and a description of the state of the project at the time.&lt;br /&gt;
&lt;br /&gt;
Perhaps we could also include short biographical pages for contributors that care to share their information, but I&#039;ll wait to see what the group thinks of that before jumping in myself. ~Joe G&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=The_Conception_of_EDURange&amp;diff=822</id>
		<title>The Conception of EDURange</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=The_Conception_of_EDURange&amp;diff=822"/>
		<updated>2025-06-30T16:32:05Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Created page with &amp;quot;Category:Project History and Roadmaps  Conceptually, EDURange started around 2011 when Jens, Michael Locasto, and Richard started talking about creating exercises for cybersecurity courses. The idea was generated at a dinner with Michael, Sergey Bratus, Brian Fite, and Richard. Brian was packet master for a competition called PacketWars, and he was looking for a way to be a player and not the one running the competition. He had a number of innovative ideas. He wanted...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Project History and Roadmaps]]&lt;br /&gt;
&lt;br /&gt;
Conceptually, EDURange started around 2011 when Jens, Michael Locasto, and Richard started talking about creating exercises for cybersecurity courses. The idea was generated at a dinner with Michael, Sergey Bratus, Brian Fite, and Richard. Brian was packet master for a competition called PacketWars, and he was looking for a way to be a player and not the one running the competition. He had a number of innovative ideas. He wanted a way to specify competition environments, so that they could be replicated in different frameworks and they would be comparable, i.e. a standardization methodology for attack-defense competitions. &lt;br /&gt;
&lt;br /&gt;
Michael was interested in the question of what makes a great cybersecurity expert. Someone who not only knows the tools but also how to apply them in innovative ways. For Michael, this was captured by the concept of analysis skills. It is the ability to see patterns in large complex data or systems. There were only a few frameworks available at the time: SEED labs, The Rave, and DeterLab. In our view, their exercises did not emphasize analysis, and the problem was that we could not modify them to create ones that did. A vision we had was that analysis takes time and doesn’t fit into a 2 hour slot. Sometimes you need to think about a problem for days before a breakthrough happens. Our idea was that you needed repeatable exercises that students could come back to. The closest we have come to that is the last challenge in SSH Inception, where as soon as bash runs, it logs the user out. The tension is that students want something that they can complete in a fixed short amount of time. Perhaps we need that for introductory exercises but can move away from that in the more advanced ones. Also, there are different ways to implement such an open-ended approach. It could be that the scenario can be suspended and re-started, or there would be multiple levels within the scenario, or there would be multiple versions of the scenario that require the same type of analysis.&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Keystroke_Observers&amp;diff=106</id>
		<title>Keystroke Observers</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Keystroke_Observers&amp;diff=106"/>
		<updated>2025-06-26T22:15:24Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Disambiguated terms in explanation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Demonstrations]]&lt;br /&gt;
See https://github.com/edurange/demo-keystroke-observers.&lt;br /&gt;
&lt;br /&gt;
Demonstrates a one-writer-multiple-reader message topology for log processing.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
To run it one can start:&lt;br /&gt;
 ./[https://github.com/edurange/demo-keystroke-observers/blob/main/toy_logger_tcp_0_1_3.py toy_logger_tcp_0_1_3.py]&lt;br /&gt;
Then, connect to local port 5554 and 5555 with a TTY utility such as [https://netcat.sourceforge.net netcat]:&lt;br /&gt;
 nc 127.0.0.1 5554&lt;br /&gt;
5554 mocks the behavior of ttylog and analyzes the input received. 5555 demonstrates that another interface, such as the guide or web GUI, could be simultaneously monitored and handled by different behavior.&lt;br /&gt;
&lt;br /&gt;
== Explanation ==&lt;br /&gt;
This is a proposal for a new communication strategy in the log pipeline. This would exist in a place analogous to the space between [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/ttylog ttylog], [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/analyze.py analyze.py] and [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/milestone-lbl.pl milestone-lbl.pl] in the current implementation; see also https://github.com/edurange/edurange3/tree/main/scenarios/global_scripts.&lt;br /&gt;
&lt;br /&gt;
LineByLineTotalizer buffers incoming data until a newline character is observed, similar to analyze.py used in previous versions. There has previously been interest in the timing not just between newlines, but all keystrokes. But analyze.py does not record this.&lt;br /&gt;
&lt;br /&gt;
ImmediateTotalizer, FixedIntervalTotalizer and DynamicIntervalTotalizer demonstrate alternative policies for how often to count and potentially timestamp the contents of the input buffer. These classes implement the [[wikipedia:Observer_pattern|Observer]] pattern as a Python [https://typing.python.org/en/latest/spec/protocol.html protocol] (update()), allowing them to respond to messages broadcast from Subject instances. See observerdemo_0_1_1.py.&lt;br /&gt;
&lt;br /&gt;
By broadcasting log events to all Observer instances, every log processor can have equal access to the original log data without resource conflicts or individual synchronization. See toy_logger_tcp_0_1_3.py.&lt;br /&gt;
&lt;br /&gt;
Rather than continue to modify and grow the features/responsibilities of analyze.py, I propose this method of creating a data pipeline that obeys the [[wikipedia:Open–closed_principle|Open-Closed Principle]], meaning that it is closed to code changes, but open to behavior extension by means of a pluggable interface; in this example, Subject.attach(). See observerdemo_0_1_1.py.&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=105</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=105"/>
		<updated>2025-06-26T21:25:09Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the EDURange Wiki. This is less of a formal documentation as it is a living document.&lt;br /&gt;
&lt;br /&gt;
I think that if it&#039;s a choice between losing track of people&#039;s contributions and having a messy wiki, I&#039;d much prefer a messy wiki.  It&#039;s my hope that we can gather all of our notes, thoughts, and loosely related ephemera here, rather than having it scattered across correspondence and various sharing platforms.&lt;br /&gt;
&lt;br /&gt;
We don&#039;t have many conventions yet. Please follow the Golden Rule and treat others as you would be treated. Put your name on your changes. Consider posting to the discussion tab or appending to a page rather than overwriting it. Try not to overwrite the personal work of others.&lt;br /&gt;
&lt;br /&gt;
If it&#039;s installable/runnable/code of any sort, put it on GitHub as well - preferably under the edurange organization so that our future contributors will have seamless access to it too.&lt;br /&gt;
&lt;br /&gt;
Thanks for your time.&lt;br /&gt;
&lt;br /&gt;
~Joe G&lt;br /&gt;
&lt;br /&gt;
== The EDURange Project ==&lt;br /&gt;
[[Project History and Roadmaps]]&lt;br /&gt;
&lt;br /&gt;
== Developer Links ==&lt;br /&gt;
[[Style Guidelines and Developer Tools]]&lt;br /&gt;
&lt;br /&gt;
[[Reference Materials]]&lt;br /&gt;
&lt;br /&gt;
[[:Category:Demonstrations|Demonstrations]]&lt;br /&gt;
&lt;br /&gt;
[[Design Stories (OLD)]]&lt;br /&gt;
&lt;br /&gt;
[[Interface Design]]&lt;br /&gt;
&lt;br /&gt;
[[Scenario Creation Guide]]&lt;br /&gt;
&lt;br /&gt;
[[Terraform Design]]&lt;br /&gt;
&lt;br /&gt;
[[Hosting Requirements]]&lt;br /&gt;
&lt;br /&gt;
[[Domain Modeling]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We&#039;re still figuring out Media Wiki, so I kept the following...&lt;br /&gt;
&lt;br /&gt;
== Orphaned Default Media Wiki Content ==&lt;br /&gt;
&amp;lt;strong&amp;gt;Welcome to the EDURange Wiki&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Consult the [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents User&#039;s Guide] for information on using the wiki software.&lt;br /&gt;
&lt;br /&gt;
== Getting started with Media Wiki ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Configuration settings list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]&lt;br /&gt;
* [https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/ MediaWiki release mailing list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Reference_Materials&amp;diff=104</id>
		<title>Reference Materials</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Reference_Materials&amp;diff=104"/>
		<updated>2025-06-26T21:23:42Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have hard copies of many of these titles available to borrow. ~Joe G&lt;br /&gt;
* Manifesto for Agile Software Development&lt;br /&gt;
** Available free online at https://agilemanifesto.org/&lt;br /&gt;
* Agile Software Development: Principles, Patterns, and Practices by Robert Martin&lt;br /&gt;
* Architecture Patterns with Python: Enabling Test-Driven Development, Domain-Driven Design, and Event-Driven Microservices by Harry Percival, Bob Gregory&lt;br /&gt;
** Available free online at http://cosmicpython.com/&lt;br /&gt;
* Test-Driven Development with Python: Obey the Testing Goat: Using Django, Selenium, and JavaScript by Harry Percival&lt;br /&gt;
** Available free online at http://www.obeythetestinggoat.com/&lt;br /&gt;
* Domain-Driven Design by Eric Evans&lt;br /&gt;
* Implementing Domain-Driven Design by Vaughn Vernon&lt;br /&gt;
* Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma et al&lt;br /&gt;
* Agile Software Development with Scrum by Ken Schwaber, Mike Beedle&lt;br /&gt;
* The Pragmatic Programmer: From Journeyman to Master by Andrew Hunt, David Thomas&lt;br /&gt;
* Extreme Programming Explained: Embrace Change by Kent Beck, Cynthia Andres&lt;br /&gt;
* Test Driven Development: By Example by Kent Beck&lt;br /&gt;
* Articulating Design Decisions by Tom Greever&lt;br /&gt;
* Python Testing with pytest by Brian Okken&lt;br /&gt;
* Unit Testing: Principles, Practices and Patterns by Vladimir Khorikov&lt;br /&gt;
* Effective Python by Brett Slatkin&lt;br /&gt;
* Robust Python: Write Clean and Maintainable Code by Patrick Viafore&lt;br /&gt;
* Python in Practice: Create Better Programs Using Concurrency, Libraries, and Patterns by Mark Summerfield&lt;br /&gt;
* Fluent Python: Clear, Concise, and Effective Programming by Luciano Ramalho&lt;br /&gt;
* Growing Object-Oriented Software, Guided by Tests by Steve Freeman, Nat Pryce&lt;br /&gt;
* Essential Software Architecture by Ian Gorton&lt;br /&gt;
* Refactoring: Improving the Design of Existing Code by Paul Becker, Martin Fowler, Kent Beck&lt;br /&gt;
* Practical UNIX by Steve Moritsugu&lt;br /&gt;
* Unix in a Nutshell: System V Edition by Arnold Robbins&lt;br /&gt;
* Unix System V: A Practical Guide by Mark G Sobell&lt;br /&gt;
* The Design of the UNIX Operating System by Maurice Bach&lt;br /&gt;
* The UNIX Programming Environment by Brian W Kernighan&lt;br /&gt;
* Programming Perl by Tom Christiansen, Brian Foy, Larry Wall&lt;br /&gt;
* The New Hacker&#039;s Dictionary by Guy L. Steele&lt;br /&gt;
* The Algorithm Design Manual by Steven Skeina&lt;br /&gt;
* Structure and Interpretation of Computer Programs by Harold Abelson, Jay Sussman, Julie Sussman&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=98</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Main_Page&amp;diff=98"/>
		<updated>2025-06-26T21:00:50Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Add link for new category: project history&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the EDURange Wiki. This is less of a formal documentation as it is a living document.&lt;br /&gt;
&lt;br /&gt;
I think that if it&#039;s a choice between losing track of people&#039;s contributions and having a messy wiki, I&#039;d much prefer a messy wiki.  It&#039;s my hope that we can gather all of our notes, thoughts, and loosely related ephemera here, rather than having it scattered across correspondence and various sharing platforms.&lt;br /&gt;
&lt;br /&gt;
We don&#039;t have many conventions yet. Please follow the Golden Rule and treat others as you would be treated. Put your name on your changes. Consider posting to the discussion tab or appending to a page rather than overwriting it. Try not to overwrite the personal work of others.&lt;br /&gt;
&lt;br /&gt;
If it&#039;s installable/runnable/code of any sort, put it on GitHub as well - preferably under the edurange organization so that our future contributors will have seamless access to it too.&lt;br /&gt;
&lt;br /&gt;
Thanks for your time.&lt;br /&gt;
&lt;br /&gt;
~Joe G&lt;br /&gt;
&lt;br /&gt;
== The EDURange Project ==&lt;br /&gt;
[[Project History and Roadmaps]]&lt;br /&gt;
&lt;br /&gt;
== Developer Links ==&lt;br /&gt;
[[Style Guidelines and Developer Tools]]&lt;br /&gt;
&lt;br /&gt;
[[Reference Materials]]&lt;br /&gt;
&lt;br /&gt;
[[:Category:Demonstrations|Demonstrations]]&lt;br /&gt;
&lt;br /&gt;
[[Design Stories (OLD)]]&lt;br /&gt;
&lt;br /&gt;
[[Interface Design]]&lt;br /&gt;
&lt;br /&gt;
[[Scenario Creation Guide]]&lt;br /&gt;
&lt;br /&gt;
[[Terraform Design]]&lt;br /&gt;
&lt;br /&gt;
[[Hosting Requirements]]&lt;br /&gt;
&lt;br /&gt;
[[Domain Modeling]]&lt;br /&gt;
&lt;br /&gt;
== Orphaned Default Media Wiki Content ==&lt;br /&gt;
&amp;lt;strong&amp;gt;Welcome to the EDURange Wiki&amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Consult the [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents User&#039;s Guide] for information on using the wiki software.&lt;br /&gt;
&lt;br /&gt;
== Getting started with Media Wiki ==&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Configuration settings list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ MediaWiki FAQ]&lt;br /&gt;
* [https://lists.wikimedia.org/postorius/lists/mediawiki-announce.lists.wikimedia.org/ MediaWiki release mailing list]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localise MediaWiki for your language]&lt;br /&gt;
* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Learn how to combat spam on your wiki]&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=96</id>
		<title>TTY Logging with BPF</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=96"/>
		<updated>2025-06-20T20:32:32Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Instructions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Demonstrations]]&lt;br /&gt;
See https://github.com/edurange/demo-bpf-tty-logger.&lt;br /&gt;
&lt;br /&gt;
Demonstrates how to capture TTY activity using BPF kernel probes.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
To run it one needs to have superuser privileges (for kernel access). The probes intercept all TTY activity on the host system - both inside and outside of containers. If the script is printing to a TTY device the prints themselves will also be observed, creating a feedback loop that will quickly consume the kernel buffers. As such the output should be redirected to a file. I recommend redirecting both STDOUT and STDERR as follows:&lt;br /&gt;
 sudo python3 [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] &amp;amp;&amp;gt; log&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Category:Demonstrations&amp;diff=92</id>
		<title>Category:Demonstrations</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Category:Demonstrations&amp;diff=92"/>
		<updated>2025-06-20T19:01:37Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Demo Projects */ Fixed wrong URL&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Let&#039;s collect self-contained examples and demos here. I&#039;m imagining this to be a space for demos that don&#039;t link to the main software stack, and focus on implementing a single feature or concept at a time.&lt;br /&gt;
&lt;br /&gt;
Preferably, they should use no external dependencies, or have only a single external dependency. They should be easy to install and run without extra knowledge - the main usage method should be readily apparent and the code should follow documentation conventions.&lt;br /&gt;
&lt;br /&gt;
Most importantly, these should be short and easy to read, because their purpose is to teach the group. It would be great if we could demonstrate, discuss and come to understand these projects within one or two group meetings.&lt;br /&gt;
&lt;br /&gt;
== Demo Projects ==&lt;br /&gt;
These demonstrate or introduce new concepts, conventions, libraries, patterns, etc.&lt;br /&gt;
&lt;br /&gt;
* [[Namedpipe Log Writer]] - https://github.com/edurange/demo-namedpipe-log-writer&lt;br /&gt;
* [[Keystroke Observers]] - https://github.com/edurange/demo-keystroke-observers&lt;br /&gt;
* [[TTY Logging with BPF]] - https://github.com/edurange/demo-bpf-tty-logger/&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Category:Demonstrations&amp;diff=91</id>
		<title>Category:Demonstrations</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Category:Demonstrations&amp;diff=91"/>
		<updated>2025-06-20T18:56:24Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: /* Demo Projects */ Add TTY Logging with BPF demo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Let&#039;s collect self-contained examples and demos here. I&#039;m imagining this to be a space for demos that don&#039;t link to the main software stack, and focus on implementing a single feature or concept at a time.&lt;br /&gt;
&lt;br /&gt;
Preferably, they should use no external dependencies, or have only a single external dependency. They should be easy to install and run without extra knowledge - the main usage method should be readily apparent and the code should follow documentation conventions.&lt;br /&gt;
&lt;br /&gt;
Most importantly, these should be short and easy to read, because their purpose is to teach the group. It would be great if we could demonstrate, discuss and come to understand these projects within one or two group meetings.&lt;br /&gt;
&lt;br /&gt;
== Demo Projects ==&lt;br /&gt;
These demonstrate or introduce new concepts, conventions, libraries, patterns, etc.&lt;br /&gt;
&lt;br /&gt;
* [[Namedpipe Log Writer]] - https://github.com/edurange/demo-namedpipe-log-writer&lt;br /&gt;
* [[Keystroke Observers]] - https://github.com/edurange/demo-keystroke-observers&lt;br /&gt;
* [[TTY Logging with BPF]] - https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=90</id>
		<title>TTY Logging with BPF</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=TTY_Logging_with_BPF&amp;diff=90"/>
		<updated>2025-06-20T18:55:22Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Created page with &amp;quot;Category:Demonstrations See https://github.com/edurange/demo-bpf-tty-logger.  Demonstrates how to capture TTY activity using BPF kernel probes.  == Instructions == To run it one needs to have superuser privileges (for kernel access). The probes intercept all TTY activity on the host system - both inside and outside of containers. If the script is printing to a TTY device the prints will also be observed, creating a feedback loop that will quickly consume the kernel b...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Demonstrations]]&lt;br /&gt;
See https://github.com/edurange/demo-bpf-tty-logger.&lt;br /&gt;
&lt;br /&gt;
Demonstrates how to capture TTY activity using BPF kernel probes.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
To run it one needs to have superuser privileges (for kernel access). The probes intercept all TTY activity on the host system - both inside and outside of containers. If the script is printing to a TTY device the prints will also be observed, creating a feedback loop that will quickly consume the kernel buffers. As such the output should be redirected to a file. I recommend redirecting both STDOUT and STDERR as follows:&lt;br /&gt;
 sudo python3 [https://github.com/edurange/demo-bpf-tty-logger/blob/main/parrotty.py parrotty.py] &amp;amp;&amp;gt; log&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
	<entry>
		<id>http://edurange.org/wiki/index.php?title=Keystroke_Observers&amp;diff=89</id>
		<title>Keystroke Observers</title>
		<link rel="alternate" type="text/html" href="http://edurange.org/wiki/index.php?title=Keystroke_Observers&amp;diff=89"/>
		<updated>2025-06-20T18:53:47Z</updated>

		<summary type="html">&lt;p&gt;Jwgranville: Touch up style&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Demonstrations]]&lt;br /&gt;
See https://github.com/edurange/demo-keystroke-observers.&lt;br /&gt;
&lt;br /&gt;
Demonstrates a one-writer-multiple-reader message topology for log processing.&lt;br /&gt;
&lt;br /&gt;
== Instructions ==&lt;br /&gt;
To run it one can start:&lt;br /&gt;
 ./[https://github.com/edurange/demo-keystroke-observers/blob/main/toy_logger_tcp_0_1_3.py toy_logger_tcp_0_1_3.py]&lt;br /&gt;
Then, connect to local port 5554 and 5555 with a TTY utility such as [https://netcat.sourceforge.net netcat]:&lt;br /&gt;
 nc 127.0.0.1 5554&lt;br /&gt;
5554 mocks the behavior of ttylog and analyzes the input received. 5555 demonstrates that another interface, such as the guide or web GUI, could be simultaneously monitored and handled by different behavior.&lt;br /&gt;
&lt;br /&gt;
== Explanation ==&lt;br /&gt;
This is a proposal for a new communication strategy in the log pipeline. This would exist in a place analogous to the space between [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/ttylog ttylog], [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/analyze.py analyze.py] and [https://github.com/edurange/edurange3/blob/main/scenarios/global_scripts/milestone-lbl.pl milestone-lbl.pl] in the current implementation; see also https://github.com/edurange/edurange3/tree/main/scenarios/global_scripts.&lt;br /&gt;
&lt;br /&gt;
LineByLineTotalizer buffers incoming data until a newline character is observed, similar to analyze.py used in previous versions. There has previously been interest in the timing not just between newlines, but all keystrokes. But analyze.py does not record this.&lt;br /&gt;
&lt;br /&gt;
ImmediateTotalizer, FixedIntervalTotalizer and DynamicIntervalTotalizer demonstrate alternative policies for how often to count and potentially timestamp the contents of the input buffer. These classes implement the [[wikipedia:Observer_pattern|Observer]] [https://typing.python.org/en/latest/spec/protocol.html protocol] (update()), allowing them to respond to messages broadcast from Subject instances. See observerdemo_0_1_1.py.&lt;br /&gt;
&lt;br /&gt;
By broadcasting log events to all Observer instances, every log processor can have equal access to the original log data without resource conflicts or individual synchronization. See toy_logger_tcp_0_1_3.py.&lt;br /&gt;
&lt;br /&gt;
Rather than continue to modify and grow the features/responsibilities of analyze.py, I propose this method of creating a data pipeline that obeys the [[wikipedia:Open–closed_principle|Open-Closed Principle]], meaning that it is closed to code changes, but open to behavior extension by means of a pluggable interface; in this example, Subject.attach(). See observerdemo_0_1_1.py.&lt;/div&gt;</summary>
		<author><name>Jwgranville</name></author>
	</entry>
</feed>