Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
141 commits
Select commit Hold shift + click to select a range
ee69eaf
adjusted update from google api to use async generator
bradley-erickson Oct 25, 2024
0bac912
fixed small bug in yield statements
bradley-erickson Oct 25, 2024
5127ea7
fixed possible create_task bug (#192)
bradley-erickson Oct 30, 2024
5ad48ab
Bump rollup from 2.79.1 to 2.79.2 in /modules/lo_dash_react_component…
dependabot[bot] Nov 4, 2024
45d1c38
Bump cookie and express in /modules/lo_dash_react_components (#183)
dependabot[bot] Nov 4, 2024
fdf00ea
Bump elliptic from 6.5.7 to 6.6.0 in /modules/lo_dash_react_component…
dependabot[bot] Nov 4, 2024
0105345
added communication protocol readme to documentation
bradley-erickson Nov 4, 2024
22bf450
updated npm packages for lo_event
pbrost Nov 6, 2024
4ff4f3a
Abstracted current gpt responders to their own module (#178)
bradley-erickson Nov 7, 2024
cc3a4b7
small installation fixes
bradley-erickson Nov 7, 2024
78723f9
Update to redux-thunk and compile error fix
pbrost Nov 8, 2024
e6a922c
import thunk statement change
pbrost Nov 8, 2024
d413030
Make sure b.storage defaults to thunk if not sync or local
pbrost Nov 8, 2024
ad9d485
code compiling for deployment of toy-sba (#198)
bradley-erickson Nov 14, 2024
83cdafb
LO Event improvements
bradley-erickson Nov 19, 2024
7ea2abb
updated lodrc package.json and webpack config to build properly
bradley-erickson Nov 19, 2024
5e4eaca
fixed gpt dashboard flashing
bradley-erickson Nov 21, 2024
e767cae
fixed auth bug when visiting a page after session expired
bradley-erickson Nov 26, 2024
2e07dd6
Update reconstruct_doc.py
PDDeane Nov 27, 2024
ccb36fd
Update reconstruct_doc.py
PDDeane Nov 27, 2024
3eeea21
Update reconstruct_doc.py
PDDeane Nov 27, 2024
aabd807
Added additional actions for `rplc` and `rvrt`
bradley-erickson Dec 4, 2024
5020beb
extension fixes to extract document history (#204)
bradley-erickson Dec 13, 2024
b79648d
Module verioning updates and some testing next steps
bradley-erickson Dec 17, 2024
257bae3
added dashboard to demo LOConnection and helper utilities (#180)
bradley-erickson Dec 17, 2024
0ba3c08
cleaned up installation
bradley-erickson Dec 20, 2024
375103a
updated requirements (#208)
bradley-erickson Jan 2, 2025
f6cc2b2
Bump nanoid from 3.3.7 to 3.3.8 in /modules/lo_dash_react_components …
dependabot[bot] Jan 23, 2025
e6d405f
Bump path-to-regexp and express in /modules/lo_dash_react_components …
dependabot[bot] Jan 23, 2025
783c904
Save state in LO Event (#209)
bradley-erickson Feb 25, 2025
e86f39f
updated classroom text highlighter component
bradley-erickson Feb 26, 2025
5544fa8
Merge branch 'master' of github.com:ETS-Next-Gen/writing_observer
bradley-erickson Feb 26, 2025
1b7b3ac
Homepage improvements (#215)
bradley-erickson Apr 1, 2025
760c5e1
added new options to llm dashboard - students per row, height, indivi…
bradley-erickson Apr 1, 2025
4470b70
Bump @babel/helpers in /modules/lo_dash_react_components (#217)
dependabot[bot] Apr 1, 2025
9eea22f
Bump @babel/runtime in /modules/lo_dash_react_components (#218)
dependabot[bot] Apr 1, 2025
7e28238
languagetool startup and highlight dashboard improvements
bradley-erickson Apr 3, 2025
c336d5d
fixed module names
bradley-erickson Apr 3, 2025
3bdcc7c
small js bug fixes for dashboards
bradley-erickson Apr 3, 2025
bee90d1
add process metrics to dashboards
bradley-erickson May 6, 2025
e4e4adf
LTI auth + Canvas/Schoology integration
bradley-erickson Jun 11, 2025
28cb3ec
Update rosters.py
bradley-erickson Jul 10, 2025
a6724ed
Workshop updates (#230)
bradley-erickson Jul 16, 2025
f61cb8b
Various improvements to serving as an LTI
bradley-erickson Aug 10, 2025
4d8e2b4
added nginx conf
bradley-erickson Aug 15, 2025
381ec66
restructured documentation (#236)
bradley-erickson Sep 19, 2025
fb5631b
Updated extension to only connect when relevant tabs are present (#235)
bradley-erickson Sep 22, 2025
eb453bf
added some tutorials
bradley-erickson Sep 23, 2025
dfa95f9
updated extension documentation
bradley-erickson Sep 23, 2025
a3fa17c
removed unused extension files
bradley-erickson Sep 23, 2025
bad6fdb
added comm protocol concept doc and updated event doc
bradley-erickson Sep 25, 2025
1c72d9e
more descriptive table of contents plus initial communication protoco…
bradley-erickson Sep 25, 2025
d604798
updated documentation for modules
bradley-erickson Sep 30, 2025
8b205d0
updated system settings documentation
bradley-erickson Oct 1, 2025
f12616b
added documentation for serving as lti
bradley-erickson Oct 1, 2025
7706b5a
updated dashboard documentation
bradley-erickson Oct 13, 2025
ec3193c
Small communication protocol fixes
bradley-erickson Oct 13, 2025
c3469ce
added missing timestamp info
bradley-erickson Oct 14, 2025
faff12b
added basic service worker config to writing extension
bradley-erickson Oct 15, 2025
1073452
added more context to documentation and added multiple roster source …
bradley-erickson Oct 20, 2025
87861f3
Change Popover trigger from 'click' to 'focus'
bradley-erickson Oct 23, 2025
3ff5ed7
added kvs documentation and referenced based on tutorial feedback
bradley-erickson Oct 28, 2025
c84a348
Added communication protocol endpoing logging ability
bradley-erickson Nov 3, 2025
b8ce707
fixed static json endpoint for modules
bradley-erickson Nov 19, 2025
fa3a15f
added note to student id mapping about where to run the command from
bradley-erickson Nov 19, 2025
c1eabcb
Ability to serve LO Blocks via LO while signing in through Canvas (#246)
bradley-erickson Dec 16, 2025
65cc64d
Bump http-proxy-middleware in /modules/lo_dash_react_components (#222)
dependabot[bot] Dec 16, 2025
c8383aa
Bump webpack-dev-server in /modules/lo_dash_react_components (#225)
dependabot[bot] Dec 16, 2025
08cc2b2
Bump on-headers and compression in /modules/lo_dash_react_components …
dependabot[bot] Dec 16, 2025
18f04ee
Bump form-data from 3.0.2 to 3.0.4 in /modules/lo_dash_react_componen…
dependabot[bot] Dec 16, 2025
07ead87
Bump js-yaml from 3.14.1 to 3.14.2 in /modules/lo_dash_react_componen…
dependabot[bot] Dec 16, 2025
1003121
Bump node-forge from 1.3.1 to 1.3.2 in /modules/lo_dash_react_compone…
dependabot[bot] Dec 16, 2025
0a37769
various small comments that I missed in a previous commit
bradley-erickson Jan 5, 2026
b80005f
documented roster and courselist format
bradley-erickson Jan 6, 2026
0984e08
updated and documented offline reducer replay
bradley-erickson Jan 6, 2026
17387e3
abstracted time on task reducers to common area to allow for more mod…
bradley-erickson Jan 14, 2026
d2a08f2
updated keys node in communication protocol to support more scoped it…
bradley-erickson Jan 15, 2026
ff07047
added basic integration logger with pmss setting (#255)
bradley-erickson Jan 20, 2026
7e55cfc
added ability to pass in pmss rulesets via command line arguments (#258)
bradley-erickson Jan 22, 2026
3866327
updated blacklist code to check for domain and determine action by se…
bradley-erickson Jan 26, 2026
b1e0dd6
Fixing comm protocol so roster is called multiple times for single da…
bradley-erickson Feb 2, 2026
deeac6f
Bump lodash from 4.17.21 to 4.17.23 in /modules/lo_dash_react_compone…
dependabot[bot] Feb 2, 2026
049e0ec
Added tab ids to extension, updated reconstruction to include tabs, a…
bradley-erickson Feb 2, 2026
5f75e49
Added ability to scope to a single value in execution dag
bradley-erickson Feb 3, 2026
ed89669
fix: arglab package new URL (#269)
OmarIthawi Feb 18, 2026
13cb495
updated links to repo and rawgit to jsdeliver (#268)
bradley-erickson Feb 19, 2026
c20cfe1
dashboard updates (#267)
bradley-erickson Feb 22, 2026
40d17a5
individual student writing portfolio dashboard (#271)
bradley-erickson Mar 4, 2026
377c68e
copy paste reducer with dashboard metrics
bradley-erickson Mar 6, 2026
94f071d
fixed coloring and typos on dashboard
bradley-erickson Mar 12, 2026
b17c2ec
updated portfolio diff to include config file so we can reuse the sam…
bradley-erickson Mar 12, 2026
c200ac3
added manifest and updated setup to include build files when installing
bradley-erickson Mar 12, 2026
a9a3177
added basic startup checks
bradley-erickson Mar 13, 2026
bc144fc
added startup commands to download files and set the runtime config b…
bradley-erickson Mar 13, 2026
fa70160
updated git ignore to be module level
bradley-erickson Mar 13, 2026
ed3b6ac
updated build documentation
bradley-erickson Mar 13, 2026
956719b
added local lorem file and removed dependency (#280)
bradley-erickson Mar 13, 2026
dfd9d08
updated lo assets directory
bradley-erickson Mar 16, 2026
1ae4755
Merge branch 'master' into berickson/20260312-small-fixes
bradley-erickson Mar 16, 2026
7fc56e7
Merge pull request #279 from ArgLab/berickson/20260312-small-fixes
DrLynch Mar 18, 2026
02f5dbc
Bump flatted from 3.3.2 to 3.4.2 in /modules/lo_dash_react_components…
dependabot[bot] Mar 31, 2026
e0976e6
Bump picomatch from 2.3.1 to 2.3.2 in /modules/lo_dash_react_componen…
dependabot[bot] Mar 31, 2026
0cb06a8
Bump brace-expansion in /modules/lo_dash_react_components (#289)
dependabot[bot] Mar 31, 2026
060fd61
Bump node-forge from 1.3.2 to 1.4.0 in /modules/lo_dash_react_compone…
dependabot[bot] Mar 31, 2026
3402a55
Bump path-to-regexp and express in /modules/lo_dash_react_components …
dependabot[bot] Mar 31, 2026
9116140
Bump rollup from 2.79.2 to 2.80.0 in /modules/lo_dash_react_component…
dependabot[bot] Mar 31, 2026
a666e0d
Bump @remix-run/router and react-router-dom (#249)
dependabot[bot] Mar 31, 2026
6ac79e0
Bump react-router and react-router-dom (#250)
dependabot[bot] Mar 31, 2026
d75adce
added pmss file watch to settings (#292)
bradley-erickson Apr 1, 2026
155c96a
added startup checks for lti provider's keys and features flags (#293)
bradley-erickson Apr 1, 2026
519a99f
Extension reconnect, copy / paste reducer fixes, and small portfolio …
bradley-erickson Apr 21, 2026
6b46a00
Bump webpack from 5.96.1 to 5.105.0 in /modules/lo_dash_react_compone…
dependabot[bot] Apr 22, 2026
f82c7ba
added more documentation around pmss rulesets and updated some other …
bradley-erickson Apr 23, 2026
c3ea413
updated offline docs to also include settings
bradley-erickson Apr 23, 2026
ebf3778
added lo assets documentation
bradley-erickson Apr 23, 2026
c8e7590
added module inventory list
bradley-erickson Apr 23, 2026
93fdf51
added comments to dockerfile
bradley-erickson Apr 23, 2026
8174e13
trying out test fixes
bradley-erickson Apr 23, 2026
f1efce8
more test fixes
bradley-erickson Apr 23, 2026
45bcf43
updated requirements to fix legacy url
bradley-erickson Apr 23, 2026
623fa1e
updated tsvx
bradley-erickson Apr 23, 2026
a0d3a8e
moved package imports to different location
bradley-erickson Apr 23, 2026
9c7101a
moved kafka import
bradley-erickson Apr 23, 2026
887fd5d
moved kafka import to try except
bradley-erickson Apr 23, 2026
36127c0
fixed doctests
bradley-erickson Apr 23, 2026
27a99b5
Bump qs and express in /modules/lo_dash_react_components (#266)
dependabot[bot] Apr 28, 2026
50837a1
Bump ajv from 6.12.6 to 6.14.0 in /modules/lo_dash_react_components (…
dependabot[bot] Apr 28, 2026
0b04b85
Bump minimatch in /modules/lo_dash_react_components (#274)
dependabot[bot] Apr 28, 2026
18ac7c0
Bump immutable from 5.0.3 to 5.1.5 in /modules/lo_dash_react_componen…
dependabot[bot] Apr 28, 2026
7e868bd
Bump yaml in /modules/lo_dash_react_components (#287)
dependabot[bot] Apr 28, 2026
eeba892
Bump lodash from 4.17.23 to 4.18.1 in /modules/lo_dash_react_componen…
dependabot[bot] Apr 28, 2026
fd7e481
Bump follow-redirects in /modules/lo_dash_react_components (#298)
dependabot[bot] Apr 28, 2026
2b3bdf4
Bump next from 13.5.5 to 15.5.15 in /modules/toy-assess (#295)
dependabot[bot] Apr 28, 2026
0caad0d
Bump next from 15.3.5 to 15.5.15 in /modules/portfolio_diff (#297)
dependabot[bot] Apr 28, 2026
6b57d0d
Bump jsonpath from 1.1.1 to 1.3.0 in /modules/lo_dash_react_component…
dependabot[bot] May 4, 2026
43c7564
Merge pull request #300 from ArgLab/berickson/20260423-documentation
DrLynch May 13, 2026
816efc9
Merge branch 'master' into berickson/20260423-test-fix
DrLynch May 15, 2026
df61ab7
Merge pull request #301 from ArgLab/berickson/20260423-test-fix
DrLynch May 18, 2026
c99f98d
Updating.
DrLynch May 18, 2026
3bfa711
improve essay comparison, trajectory forecasting, and fix metric reads
JohnDamilola Jun 8, 2026
9b18dcd
Improve essay comparison, trajectory forecasting, and fix metric read…
JohnDamilola Jun 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ learning_observer/learning_observer/static_data/google/
learning_observer/learning_observer/static_data/admins.yaml
.ipynb_checkpoints/
.eggs/
.next/
.next/
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ FROM python:3.10
RUN git config --global --add safe.directory /app
WORKDIR /app

# Future work:
# - This image currently uses an older Python base image version.
# - Update the Python version to align with current LO/WO support targets.
# - Some configurations may also require extra roster files mounted/provided
# at runtime (for example: admins.yaml or teachers.yaml).
# - Consider a layered setup:
# 1) maintain a shared "base LO" Docker image
# 2) extend it with a WO-specific image (or other module-set images)

# TODO start redis in here
# see about docker loopback
RUN apt-get update && \
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ install: install-pre-commit-hook
# recent version. We would like to directly fetch `lodrc-current`,
# however, the fetch only returns the name of the file it's
# linked to. We do an additional fetch for the linked file.
@LODRC_CURRENT=$$(curl -s https://raw.githubusercontent.com/ETS-Next-Gen/lo_assets/main/lo_dash_react_components/lo_dash_react_components-current.tar.gz); \
pip install https://raw.githubusercontent.com/ETS-Next-Gen/lo_assets/main/lo_dash_react_components/$${LODRC_CURRENT}
@LODRC_CURRENT=$$(curl -s https://raw.githubusercontent.com/ArgLab/lo_assets/main/lo_dash_react_components/lo_dash_react_components-current.tar.gz); \
pip install https://raw.githubusercontent.com/ArgLab/lo_assets/main/lo_dash_react_components/$${LODRC_CURRENT}

install-dev:
# TODO create a dev requirements file
Expand Down
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ learning analytics dashboard to help instructors be able to manage
student learning processes, and in particular, student writing
processes.

![linting](https://github.com/ETS-Next-Gen/writing_observer/actions/workflows/pycodestyle.yml/badge.svg)
![linting](https://github.com/ArgLab/writing_observer/actions/workflows/pycodestyle.yml/badge.svg)

## Learning Observer

Expand All @@ -17,6 +17,14 @@ per-student writing data, and aggegators to make dashboards. We've
tested this in math and writing, but our focus is on writing process
data.

At a high level, Learning Observer functions as an application platform.
The primary `learning_observer` module bootstraps the system: it loads
configuration, connects to storage and messaging back ends, and brokers
communication with data sources. Other modules plug into that
infrastructure to define the specific reducers, dashboards, and other
items that users interact with, letting teams experiment with new
features without having to reimplement the platform core.

It's not finished, but it's moving along quickly.

## Writing Observer
Expand Down Expand Up @@ -54,9 +62,10 @@ that the core approach and APIs are correct.

## Getting Started

We have a short guide to [getting started](docs/workshop.md). Getting
the base system working is pretty easy. The guide is pretty
comprehensive (including how to develop your first module).
We have a short guide to [installing the system](docs/tutorials/install.md).
Getting the base system working is pretty easy. To create a new module
for the system to use, check out our [cookiecutter module guide](docs/tutorials/cookiecutter-module.md).
For a current package/module overview, see the [module inventory](docs/reference/module_inventory.md).

### System requirements

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0+2025.10.01T21.16.15.146Z.8b205d0c.master
0.1.0+2026.06.08T14.57.09.3NZ.c99f98d.refactor.portfolio.diff
13 changes: 10 additions & 3 deletions autodocs/how-to.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,29 @@ How-to
Practical instructions for achieving specific goals within Learning Observer. Use these guides when you know what outcome you need and want a proven recipe to follow:

- :doc:`Communication Protocol <docs/how-to/communication_protocol>` - How to query data from reducers or system endpoints for dashboards.
- :doc:`Configure Learning Observer <docs/how-to/config>` - Set up credentials, environment variables, and other configuration details required for a smooth deployment.
- :doc:`Build Dashboards <docs/how-to/dashboards>` - Walk through creating dashboards from reducer outputs, including layout choices and data wiring.
- :doc:`LTI <docs/how-to/lti>` - Cover how to install Learning Observer as an LTI application.
- :doc:`Offline Reducer Replay <docs/how-to/offline_replay>` - Explain how to repopulate reducer content with study logs.
- :doc:`Serve as LTI application<docs/how-to/lti>` - Cover how to install Learning Observer as an LTI application.
- :doc:`Connect LO Blocks to Canvas via Learning Observer<docs/how-to/connect_lo_blocks_to_canvas>` - Show how to connect launch LO Blocks through Learning Observer from within Canvas.
- :doc:`Configure Multiple Roster Sources<docs/how-to/multiple_roster_sources>` - Allow the system to dynamically choose a roster source given a user's context.
- :doc:`Run with Docker <docs/how-to/docker>` - Learn how to containerize the stack, manage images, and operate the project using Docker Compose.
- :doc:`Writing Observer Extension <docs/how-to/extension>` - Install, configure, and validate the Writing Observer browser extension for capturing events.
- :doc:`Interactive Environments <docs/how-to/interactive_environments>` - Connect Learning Observer to Jupyter and other live coding setups for iterative development.
- :doc:`Impersonate Users <docs/how-to/impersonation>` - Start and stop acting as another user while keeping dashboards informed.


.. toctree::
:hidden:
:maxdepth: 1
:titlesonly:

docs/how-to/communication_protocol.md
docs/how-to/config.md
docs/how-to/dashboards.md
docs/how-to/offline_replay.md
docs/how-to/lti.md
docs/how-to/connect_lo_blocks_to_canvas.md
docs/how-to/multiple_roster_sources.md
docs/how-to/docker.md
docs/how-to/extension.md
docs/how-to/interactive_environments.md
docs/how-to/impersonation.md
6 changes: 6 additions & 0 deletions autodocs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ per-student writing data, and aggegators to make dashboards. We've
tested this in math and writing, but our focus is on writing process
data.

At a high level, Learning Observer operates as an application platform:
the core :mod:`learning_observer` package boots the system, loads
configured modules, and manages shared data services, while each module
provides the specific dashboards, reducers, and other artifacts that
users interact with.

Our documentation is organized into four main categories, each serving a different purpose. You can explore them below:

- :doc:`Tutorials <tutorials>` - Step-by-step guides to help you learn by doing.
Expand Down
4 changes: 4 additions & 0 deletions autodocs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Detailed, structured information about APIs, configurations, and technical detai
- :doc:`Linting Rules <docs/reference/linting>` - Review the automated checks that keep the codebase healthy and how to run them locally.
- :doc:`Testing Strategy <docs/reference/testing>` - Explore the testing layers we rely on and guidelines for writing reliable tests.
- :doc:`Versioning and Releases <docs/reference/versioning>` - See how we tag releases, manage dependencies, and maintain backward compatibility.
- :doc:`lo_assets Built Packages <docs/reference/lo_assets>` - Understand how prebuilt package artifacts are published and consumed.
- :doc:`Module Inventory <docs/reference/module_inventory>` - Get a quick at-a-glance list of current monorepo modules and their roles.
- :doc:`Module Reference <modules>` - Dive into the autogenerated API reference for Python modules within Learning Observer.
- :doc:`API Reference <api>` - Inspect the internal functionality of the system.

Expand All @@ -23,5 +25,7 @@ Detailed, structured information about APIs, configurations, and technical detai
docs/reference/linting.md
docs/reference/testing.md
docs/reference/versioning.md
docs/reference/lo_assets.md
docs/reference/module_inventory.md
modules
api
63 changes: 62 additions & 1 deletion devops/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,65 @@ We would like to be cross-platform, and evenually support both
Debian-based distros and RPM-based distros. We're not there yet
either. We'd also like to support multiple cloud providers. We're not
there yet either. However, we probably won't accept PRs which move us
away from this goal.
away from this goal.

## Create an AWS account and an EC2 instance.
* Select Ubuntu, nano AMI. The cost should be 0.5 cents per hour.
* In security groups, add HTTP, HTTPS rules. Open up only to your computer's IP address (the client).
* Launch instance.
* Suppose your instance public DNS is {ec2_ip}, e.g., ec2-18-223-122-172.us-east-2.compute.amazonaws.com.
* Create aSSH key pair, save PEM file say under ~/.ssh, chmod to u+r.

## Set up the EC2 instance.
* SSH into the machine: `bash ssh -i {pem_file} ubuntu@{ec2_ip}`.
* (Optional) Create a user account: sudo useradd {user}
* Download the server code (same repository as the extension):
```bash
cd
git clone https://github.com/ETS-Next-Gen/writing_analysis.git writing_analysis
```
* Install Ansible.
```bash
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install ansible
````
* Configure Ansible.
sudo pico /etc/ansible/hosts
Add
```
[localhost]
127.0.0.1
```
* `cd ~/writing_analysis/configuration`.
* Run `sudo ansible-playbook local.yaml`. This may take a while on an EC2 nanon machine.
If all goes well, you should see an output with no errors, like this:
```
bash
...
PLAY RECAP ******************************************************************************************
127.0.0.1 : ok=5 changed=4 unreachable=0 failed=0
```
* Navigate to http://{ec2_ip}; you should see the message "Welcome to nginx!" if it's working.

## Obtain a free domain name
* Go to noip.com.
* Sign up

## Obtain a free SSL Certificate Using Certbot
* Run the following commands:
```bash
sudo apt-get install software-properties-common
Sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx
```
```
bash
sudo certbot --nginx
```
-- Put in your {mydomain}.hopto.org address.
-- Choose 1 - no redirect.

## Stand up a backend server on the EC2 instance.
2 changes: 1 addition & 1 deletion devops/tasks/remote_scripts/gitpaths.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def gitpath_to_name(packagepath):
'''
Convert a git path to the name of the repo. For example:

`https://github.com/ETS-Next-Gen/writing_observer.git` ==> `writing_observer`
`https://github.com/ArgLab/writing_observer.git` ==> `writing_observer`
'''
package = os.path.split(packagepath)[1]
if package.endswith(".git"):
Expand Down
2 changes: 1 addition & 1 deletion devops/tasks/scripts/baseline_packages.fab
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cd
sudo apt-get -y install git ansible awscli
git clone https://github.com/ETS-Next-Gen/writing_observer.git
git clone https://github.com/ArgLab/writing_observer.git
cd writing_observer/devops/ansible ; sudo ansible-playbook local.yaml
13 changes: 12 additions & 1 deletion docs/concepts/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Piotr Mitros
## Introduction

Like all such documents, this document should be taken with a grain of
salt. It my be out-of-date, or not fully implemented.
salt. It my be out-of-date, or not fully implemented.

## Overview

Expand All @@ -19,6 +19,17 @@ salt. It my be out-of-date, or not fully implemented.
5. Consumers can aggregate these notifications, inspect the external state,
and make a dashboard.

## Application platform structure

Learning Observer acts as the shared platform that hosts and coordinates
modules. The core `learning_observer` package owns the boot process: it
loads configuration, establishes connections to databases and pub/sub
systems, and exposes the APIs modules use to register reducers,
dashboards, and other artifacts. Individual modules focus on defining
those artifacts, relying on the platform to handle data ingestion and
communication so new functionality can be added without duplicating the
runtime infrastructure.

### Technology choices

1. Generic student information (e.g. names, auth, etc.) cn live in
Expand Down
31 changes: 31 additions & 0 deletions docs/concepts/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,34 @@ authentication, safety checks, and analytics while keeping the event format
itself lightweight. Clients only need to agree on the JSON structure of events,
while the server handles durability and routing responsibilities on their
behalf.

## Configuring domain-based event blacklisting

Incoming events can be blacklisted through PMSS rules so that specific domains
either continue streaming, are told to retry later, or drop events entirely.
The `blacklist_event_action` setting controls the action and defaults to
`TRANSMIT`. Define rules under the `incoming_events` namespace and include a
`domain` attribute to scope the behavior per organization. When the action is
`MAINTAIN`, the `blacklist_time_limit` setting controls whether the client
should wait a short time or stop sending forever.

```pmss
incoming_events {
blacklist_event_action: TRANSMIT;
}

incoming_events[domain="example.org"] {
blacklist_event_action: DROP;
}

incoming_events[domain="pilot.example.edu"] {
blacklist_event_action: MAINTAIN;
blacklist_time_limit: DAYS;
}
```

When a client connects, the server extracts a candidate domain from the event
payload and uses it to resolve the `blacklist_event_action` setting. If
a rule returns `DROP`, the client is instructed to stop sending events.
`MAINTAIN` asks the client to retain events and retry after a delay (as defined
by `blacklist_time_limit`), while `TRANSMIT` streams events normally.
107 changes: 107 additions & 0 deletions docs/concepts/key_value_store.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Key-value store

Learning Observer reducers and dashboards communicate through a key-value store (KVS).
Reducers write internal state and dashboard-facing summaries to the store, while
queries and presentation layers read those JSON blobs back. The
[`learning_observer.kvs` module](../../learning_observer/learning_observer/kvs.py)
wraps the different storage backends behind a common async API.

## Router and lifecycle

The `KVSRouter` constructed during startup owns every configured backend. When
`learning_observer.prestartup` runs it reads the `kvs` section from system
settings, instantiates the requested implementations, and exposes them through
the module-level `KVS` callable. Most code imports `learning_observer.kvs.KVS`
and invokes it to obtain the default backend:

```python
from learning_observer import kvs

store = kvs.KVS() # returns the default backend configured in settings
value = await store[key]
```

Reducers obtain the store implicitly through decorators such as
`kvs_pipeline` and `student_event_reducer`. Those helpers capture the module
context, derive the reducer keys, and persist the reducer's internal and
external state back to the configured KVS.

The router also exposes named backends as attributes. If a module needs to
store data in a non-default backend it can call `kvs.KVS.<name>()` where
`<name>` matches the identifier from configuration.

## Configuring backends

The `kvs` block in `creds.yaml` (or an equivalent PMSS overlay) declares each
backend. Settings accept either a mapping or an array of key/value tuples.
Every entry must provide a `type` that matches one of the built-in
implementations:

```yaml
kvs:
default:
type: filesystem
path: .lo_kvs
redis_cache:
type: redis_ephemeral
expiry: 30
```

During startup the router validates the configuration and raises a
`StartupCheck` error if a backend is missing required parameters or references
an unknown type. Once the process finishes booting, the resulting callable is
available to the rest of the system as `learning_observer.kvs.KVS`.

### Supported types

| Type | Class | Persistence behavior | Required settings |
|------------------|-----------------------------|------------------------------------------------------------------------|-----------------------------------------------|
| `stub` | `InMemoryKVS` | Data lives only in process memory and disappears on restart. | None |
| `redis_ephemeral`| `EphemeralRedisKVS` | Uses Redis with a per-key TTL for temporary caches. | `expiry` (seconds) |
| `redis` | `PersistentRedisKVS` | Stores data in Redis without an expiry; persistence depends on Redis. | Redis connection parameters in system config. |
| `filesystem` | `FilesystemKVS` | Serializes each key to JSON on disk for simple local persistence. | `path`; optional `subdirs` boolean |

All backends share the async API: `await store[key]`, `await store.set(key, value)`,
`await store.keys()`, and `await store.dump()` for debugging.

### Filesystem layout

The filesystem implementation writes JSON documents under the configured path.
If `subdirs` is true it mirrors slash-separated key prefixes into nested
folders while prefixing directory names with underscores to avoid collisions.
This backend is convenient for workshops or debugging because state survives
restarts as long as the directory remains intact, but it is not designed for
large-scale deployments.

### Redis variants

Both Redis implementations rely on the shared connection utilities in
`learning_observer.redis_connection`. The ephemeral variant requires an
`expiry` value so it can set a TTL when calling `SET`, making it suitable for
integration tests or scratch environments. The persistent variant omits the TTL
so keys remain until explicitly deleted or until the Redis server evicts them.
Ensure the Redis instance has persistence enabled (`appendonly` or RDB
snapshots) if the deployment expects reducer state to survive reboots.

### In-memory stub

The stub backend keeps a Python dictionary in memory. It is useful for unit
tests or prototype scripts but should not be used when the process restarts or
scales across workers. The module exposes a `clear()` helper to wipe the store
between tests.

## Working with reducer state

Reducer keys follow the pattern `<scope>,<module>,<selector>` where the scope
captures whether the state is internal or external, the module identifies the
producer, and the selector encodes the entity (for example, a student ID). When
reducers process new events they read the previous state from the KVS, compute
an updated value, and call `set()` to write it back. Dashboards and protocol
adapters then fetch the external state by constructing the same key or by using
higher-level query helpers that wrap the KVS API.

If a dashboard appears empty after restarting the server, confirm which backend
is active. In-memory and ephemeral Redis stores start empty on boot, so the
system needs a fresh stream of events to repopulate reducer state. Filesystem
and persistent Redis backends retain data unless their underlying storage was
cleared.
Loading
Loading