Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ OPEN_CONTENT_TOKEN=dev-open-content-token
# The Provider Platforms service (EN-206) and the secret core shares with it.
PROVIDER_PLATFORMS_URL=http://127.0.0.1:8083
PROVIDER_PLATFORMS_TOKEN=dev-provider-platforms-token
# The Programs service and the secret core shares with it.
PROGRAMS_URL=http://127.0.0.1:8084
PROGRAMS_TOKEN=dev-programs-token
KOLIBRI_DB_PASSWORD=dev
KOLIBRI_USERNAME=SuperAdmin
KOLIBRI_PASSWORD=ChangeMe!
Expand Down Expand Up @@ -56,6 +59,14 @@ VITE_STATE=
# without a checkout, such as a PR's, set OPEN_CONTENT_REF (default main).
# OPEN_CONTENT_DIR=../unlocked-open-content
# OPEN_CONTENT_REF=main
# Provider Platforms (github.com/UnlockedLabs/unlocked-provider-platforms) is
# built the same way, with PROVIDER_PLATFORMS_DIR and PROVIDER_PLATFORMS_REF.
# PROVIDER_PLATFORMS_DIR=../unlocked-provider-platforms
# PROVIDER_PLATFORMS_REF=main
# Programs (github.com/UnlockedLabs/unlocked-programs) is built the same way,
# with PROGRAMS_DIR and PROGRAMS_REF.
PROGRAMS_DIR=../unlocked-programs
# PROGRAMS_REF=main

# Path to the AI tutor checkout (github.com/UnlockedLabs/unlocked-hiset-ai),
# relative to this repo or absolute. Defaults to ../ai/unlocked-hiset-ai.
Expand Down
19 changes: 14 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ OPEN_CONTENT_RUN=docker compose run --rm --no-deps open-content-migrate
# PROVIDER_PLATFORMS_REF from GitHub, or your checkout in PROVIDER_PLATFORMS_DIR.
PROVIDER_PLATFORMS_REPO=https://github.com/UnlockedLabs/unlocked-provider-platforms.git
PROVIDER_PLATFORMS_RUN=docker compose run --rm --no-deps providerplatforms-migrate
# Programs runs as its own service, built the same way: PROGRAMS_REF from
# GitHub, or your checkout in PROGRAMS_DIR.
PROGRAMS_REPO=https://github.com/UnlockedLabs/unlocked-programs.git
PROGRAMS_RUN=docker compose run --rm --no-deps programs-migrate
# Canvas admin created on first `make canvas`. Override in the environment if
# you want different credentials. These are also what you log into Canvas with
# at localhost:3001 to mint the API token.
Expand Down Expand Up @@ -79,6 +83,7 @@ define run_dev_compose
}; \
build_source OPEN_CONTENT "Open Content" $(OPEN_CONTENT_REPO) || exit 1; \
build_source PROVIDER_PLATFORMS "Provider Platforms" $(PROVIDER_PLATFORMS_REPO) || exit 1; \
build_source PROGRAMS "Programs" $(PROGRAMS_REPO) || exit 1; \
AI_DIR=$${TUTOR_DIR:-$$(sed -n 's/^TUTOR_DIR=//p' .env | tail -1)}; \
AI_DIR=$${AI_DIR:-$(DEFAULT_AI_DIR)}; \
TUTOR_READY=0; TUTOR_WHY=; \
Expand Down Expand Up @@ -243,22 +248,25 @@ install-dep: ascii_art
fi
docker compose down && docker volume rm -f unlockedv2_node_modules && cd frontend && yarn add $(NAME) && cd ..
$(call run_dev_compose,)
# Open Content's and Provider Platforms' migrations roll back first, since they
# move tables that core's reset drops, and run again after it. Their services
# restart because their connections switch to the role the reset recreates, and
# Open Content's worker seeds the fresh database when it starts.
# Open Content's, Provider Platforms' and Programs' migrations roll back first,
# since they move tables that core's reset drops, and run again after it. Their
# services restart because their connections switch to the role the reset
# recreates, and Open Content's worker seeds the fresh database when it starts.
migrate-fresh: ascii_art
$(OPEN_CONTENT_RUN) migrate-reset
$(PROVIDER_PLATFORMS_RUN) migrate-reset
$(PROGRAMS_RUN) migrate-reset
go run -tags dev $(MIGRATE_MAIN) --fresh
$(OPEN_CONTENT_RUN) migrate
$(PROVIDER_PLATFORMS_RUN) migrate
docker compose restart open-content open-content-worker providerplatforms providerplatforms-worker
$(PROGRAMS_RUN) migrate
docker compose restart open-content open-content-worker providerplatforms providerplatforms-worker programs programs-worker

migrate: ascii_art
go run $(MIGRATE_MAIN)
$(OPEN_CONTENT_RUN) migrate
$(PROVIDER_PLATFORMS_RUN) migrate
$(PROGRAMS_RUN) migrate

kolibri: ascii_art
$(call run_dev_compose,-f $(DOCKER_COMPOSE) -f $(KOLIBRI_COMPOSE))
Expand Down Expand Up @@ -291,6 +299,7 @@ seed: ascii_art
go run $(SEED_MAIN)
$(OPEN_CONTENT_RUN) seed-dev
$(PROVIDER_PLATFORMS_RUN) seed-dev
$(PROGRAMS_RUN) seed-dev

build: ascii_art
@if [ -z "$(ACCOUNT_ID)" ]; then \
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ branch with `PROVIDER_PLATFORMS_REF`. Core forwards its `/api` routes to it and
with `PROVIDER_PLATFORMS_TOKEN`; if you run the server outside compose, `.env.example` points
`PROVIDER_PLATFORMS_URL` at its port, 8083.

**Programs** ([unlocked-programs](https://github.com/UnlockedLabs/unlocked-programs)) runs as its
own service the same way: `make dev` builds its `main` branch from GitHub, or your checkout when
`PROGRAMS_DIR` is set (such as `../unlocked-programs`), or another branch with `PROGRAMS_REF`. Its
pages are still in core's frontend; the rev_proxy sends their `/api` paths to it, and core asks it
questions with `PROGRAMS_TOKEN`. If you run the server outside compose, `.env.example` points
`PROGRAMS_URL` at its port, 8084.


**NOTE:** you _must_ be sure to use `127.0.0.1` in place of `localhost` in your browser, as the cookies required for authentication are not shared between the two,
and this can cause bad states in the browser that will prevent successful login/auth flow.
Expand Down Expand Up @@ -130,8 +137,8 @@ If this does not work because your directory is named something different, you c
and paste the token you just copied as its `access_key`.

**Note** the base url is `http://canvas`, not `localhost:3001`. UnlockEd calls the Canvas API
from inside the `providerplatforms` and `providerplatforms-worker` containers, so it needs the
compose service name. `localhost:3001` only works from your browser.
from inside the `providerplatforms`, `providerplatforms-worker` and `programs` containers, so it
needs the compose service name. `localhost:3001` only works from your browser.


- **Videos**:
Expand Down
16 changes: 2 additions & 14 deletions backend/.golangci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
version: "2"

# golangci-lint's standard linters (what CI ran before this file existed) plus
# depguard for the feature-module boundaries (EN-190). Open Content and Provider
# Platforms aren't here: they are their own services (EN-205, EN-206).
# depguard for the feature-module boundaries (EN-190). Open Content, Provider
# Platforms and Programs aren't here: they are their own services.
linters:
default: standard
enable:
Expand All @@ -29,7 +29,6 @@ linters:
allow:
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/module
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/registry
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/programs/api
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/learningrecord/api
# The seam imports nothing from core. depguard only sees each file's
# own imports, so a core type handed to modules through the seam
Expand All @@ -42,16 +41,6 @@ linters:
desc: the module seam must not expose core types to feature modules (EN-188)
allow:
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/module
programs:
list-mode: lax
files: ["**/src/modules/programs/**"]
deny:
- pkg: github.com/UnlockedLabs/unlocked-core/backend
desc: a feature module reaches core only through src/modules/module and unlocked-contracts, and other modules only through their api package (EN-186, EN-188)
allow:
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/module
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/programs
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/learningrecord/api
learningrecord:
list-mode: lax
files: ["**/src/modules/learningrecord/**"]
Expand All @@ -61,4 +50,3 @@ linters:
allow:
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/module
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/learningrecord
- github.com/UnlockedLabs/unlocked-core/backend/src/modules/programs/api
9 changes: 6 additions & 3 deletions backend/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ func main() {
return
}
}
// The API server asks Open Content its questions, which it answers only
// with the site's secret. The dev seeder builds a server too, but never
// asks, so the check is here rather than in NewServer.
// The API server asks Open Content and Programs their questions, which
// they answer only with the site's secrets. The dev seeder builds a server
// too, but never asks, so the check is here rather than in NewServer.
if !testing && os.Getenv("OPEN_CONTENT_TOKEN") == "" {
log.Fatal("OPEN_CONTENT_TOKEN must be set: it's the secret the server asks Open Content's questions with")
}
if !testing && os.Getenv("PROGRAMS_TOKEN") == "" {
log.Fatal("PROGRAMS_TOKEN must be set: it's the secret the server asks Programs' questions with")
}
if !testing {
requireProviderPlatformsToken()
}
Expand Down
16 changes: 2 additions & 14 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,13 @@ require (
github.com/prometheus/client_golang v1.23.2
github.com/sirupsen/logrus v1.9.4
github.com/stretchr/testify v1.11.1
github.com/teambition/rrule-go v1.8.2
golang.org/x/net v0.60.0 // indirect
gorm.io/driver/postgres v1.6.0
gorm.io/gorm v1.31.1
)

require (
github.com/UnlockedLabs/unlocked-contracts v0.4.0
github.com/xuri/excelize/v2 v2.11.1-0.20260915055537-22f76f9acb94
)
require github.com/UnlockedLabs/unlocked-contracts v0.5.0

require (
github.com/richardlehane/mscfb v1.0.8 // indirect
github.com/richardlehane/msoleps v1.0.6 // indirect
github.com/tiendc/go-deepcopy v1.7.2 // indirect
github.com/xuri/efp v0.0.1 // indirect
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
)
require go.yaml.in/yaml/v2 v2.4.3 // indirect

require (
github.com/beorn7/perks v1.0.1 // indirect
Expand Down
22 changes: 2 additions & 20 deletions backend/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/UnlockedLabs/unlocked-contracts v0.4.0 h1:289y2TWKGdi1S6/DHlzxark3wZJICdEggLoyXiPfWQ4=
github.com/UnlockedLabs/unlocked-contracts v0.4.0/go.mod h1:RAEqqBigq/Gu5ARxWKsSjN34B2N3GlEyGX8DjHjKxK0=
github.com/UnlockedLabs/unlocked-contracts v0.5.0 h1:Jwr3CGeD4xtr9AXV2FXqwehuUmFi9n3+5Py9HnEzPak=
github.com/UnlockedLabs/unlocked-contracts v0.5.0/go.mod h1:RAEqqBigq/Gu5ARxWKsSjN34B2N3GlEyGX8DjHjKxK0=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
Expand Down Expand Up @@ -93,10 +93,6 @@ github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/richardlehane/mscfb v1.0.8 h1:UXdg61fxF69/X9yMYuRHAWSrGXIul/UAPivAsUXMme8=
github.com/richardlehane/mscfb v1.0.8/go.mod h1:pe0+IUIc0AHh0+teNzBlJCtSyZdFOGgV4ZK9bsoV+Jo=
github.com/richardlehane/msoleps v1.0.6 h1:9BvkpjvD+iUBalUY4esMwv6uBkfOip/Lzvd93jvR9gg=
github.com/richardlehane/msoleps v1.0.6/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
Expand All @@ -110,16 +106,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/teambition/rrule-go v1.8.2 h1:lIjpjvWTj9fFUZCmuoVDrKVOtdiyzbzc93qTmRVe/J8=
github.com/teambition/rrule-go v1.8.2/go.mod h1:Ieq5AbrKGciP1V//Wq8ktsTXwSwJHDD5mD/wLBGl3p4=
github.com/tiendc/go-deepcopy v1.7.2 h1:Ut2yYR7W9tWjTQitganoIue4UGxZwCcJy3orjrrIj44=
github.com/tiendc/go-deepcopy v1.7.2/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.11.1-0.20260915055537-22f76f9acb94 h1:yPdJeJLC1uTN8zQBHE2nqHjZ15PfxU9xsX75vNcyy/c=
github.com/xuri/excelize/v2 v2.11.1-0.20260915055537-22f76f9acb94/go.mod h1:WnwweQUkWv/3Y6OBVy0bgqN0zHAbn2N+i2zPUAXF1SI=
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
Expand All @@ -130,12 +116,8 @@ golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M=
golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA=
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
golang.org/x/image v0.44.0 h1:+tDekMZED9+LrtB3G5xzRggpVh9CARjZqROla3R3R+I=
golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY=
golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c=
golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o=
golang.org/x/net v0.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU=
golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg=
golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk=
golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
5 changes: 3 additions & 2 deletions backend/migrations/00058_drop_daily_program_tables.sql
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ CREATE TABLE IF NOT EXISTS public.daily_program_facility_history (

CREATE INDEX IF NOT EXISTS idx_daily_program_facility_history_history_date_program_id_facility_id ON public.daily_program_facility_history USING btree (date DESC, program_id, facility_id);

INSERT INTO public.cron_jobs (name, schedule, category, created_at, updated_at) VALUES
('daily_prog_history', '0 22 * * *', 3, NOW(), NOW());
-- cron_jobs.id is text with no default; the app makes it a UUID.
INSERT INTO public.cron_jobs (id, name, schedule, category, created_at, updated_at) VALUES
(gen_random_uuid()::text, 'daily_prog_history', '0 22 * * *', 3, NOW(), NOW());
-- +goose StatementEnd
10 changes: 1 addition & 9 deletions backend/migrations/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ require (
)

require (
github.com/UnlockedLabs/unlocked-contracts v0.4.0 // indirect
github.com/UnlockedLabs/unlocked-contracts v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
github.com/glebarez/go-sqlite v1.22.0 // indirect
Expand All @@ -36,19 +36,11 @@ require (
github.com/nats-io/nuid v1.0.1 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/richardlehane/mscfb v1.0.8 // indirect
github.com/richardlehane/msoleps v1.0.6 // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/teambition/rrule-go v1.8.2 // indirect
github.com/tiendc/go-deepcopy v1.7.2 // indirect
github.com/xuri/efp v0.0.1 // indirect
github.com/xuri/excelize/v2 v2.11.1-0.20260915055537-22f76f9acb94 // indirect
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.57.0 // indirect
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
golang.org/x/net v0.60.0 // indirect
golang.org/x/sync v0.23.0 // indirect
golang.org/x/sys v0.48.0 // indirect
golang.org/x/text v0.42.0 // indirect
Expand Down
Loading
Loading