Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ff584a3
:bug: Fix editor bridge shutdown to kill entire process group
klondikemarlen Apr 17, 2026
c4491c3
Merge branch 'ytgov:main' into main
klondikemarlen May 20, 2026
cc1b9d5
`access_level_department_restriction` key in template `api/src/templa…
burkkyy Jun 2, 2026
5816ead
make string empty
burkkyy Jun 2, 2026
3089a90
Merge pull request #41 from icefoganalytics/tk-70/template-showing-un…
burkkyy Jun 2, 2026
719c402
external user edit form
burkkyy Jun 4, 2026
45395f4
updating route names
burkkyy Jun 5, 2026
3b49956
Added back in slider components
burkkyy Jun 5, 2026
3a752c7
Merge pull request #42 from icefoganalytics/tk-58/editing-external-us…
burkkyy Jun 5, 2026
69ba248
chopping out new and edit pages for admin ISA
burkkyy Jun 16, 2026
a291a95
todo concept
burkkyy Jun 16, 2026
88567fd
Removing comment in favour of jira ticket https://yg-hpw.atlassian.ne…
burkkyy Jun 16, 2026
b61235a
Removing unused component
burkkyy Jun 18, 2026
64c1b5b
Adding title slot to card
burkkyy Jun 18, 2026
f4f2456
Simplifying admin ISA pages more
burkkyy Jun 18, 2026
acfb1e6
Merge pull request #44 from icefoganalytics/tk-63/creating-agreement-…
klondikemarlen Jun 19, 2026
f7a8aee
Simplifying ISA archive item create steps
burkkyy Jun 16, 2026
dc35a4f
adding back in confidentialityReceipt as its required for create
burkkyy Jun 16, 2026
52992d6
removing new archive button, since knowledge items require ISA to be …
burkkyy Jun 22, 2026
6014b99
Removing categories and tags section
burkkyy Jun 22, 2026
bdab852
ISA archive item creation moved to a dialog
burkkyy Jun 22, 2026
70ba7ff
code simplification
burkkyy Jun 29, 2026
3fa45a8
Removing share button
burkkyy Jun 29, 2026
33afd2c
Letting archive item create dialog manage its own show state
burkkyy Jun 29, 2026
42daa5a
Simplifiying frontend archive item creation futher
burkkyy Jun 29, 2026
3309466
Throw error on invalid externalGroupContactId
burkkyy Jul 15, 2026
f59f2a5
ref name
burkkyy Jul 15, 2026
7525250
removing archiveItemCategoriesAttributes
burkkyy Jul 15, 2026
0322997
Merge pull request #45 from icefoganalytics/tk-80/changes-when-creati…
burkkyy Jul 15, 2026
ec8a3fb
:memo: Repair Traditional Knowledge guidance links.
klondikemarlen Jul 14, 2026
29fc6b9
Merge pull request #47 from icefoganalytics/issue-46-guidance-audit-c…
klondikemarlen Jul 22, 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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ This project is using [knex](https://knexjs.org/guide/migrations.html#migration-

NOTE: Migrations should use snake_case. While database table and column names use snake_case, we are using Sequelize for our models so that we get camelCase to match the JS standard, in the JS section of the codebase.

1. To create a new migration from the template [sample-migration](./api/src/db/template/sample-migration.ts) do:
1. To create a new migration from the template [sample-migration](./api/src/db/templates/sample-migration.ts) do:

```bash
dev migrate make create-users-table
Expand Down
2 changes: 1 addition & 1 deletion agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ ls -li .cursor/workflows/

If you need agent-specific versions, you can:

1. **Keep in `agents/[agent-name]/`** instead of hardlinking:
1. **Keep in a dedicated `agents/` subdirectory for that agent** instead of hardlinking:
```bash
mkdir -p agents/claude/workflows
cp agents/workflows/create-admin-ui.md agents/claude/workflows/
Expand Down
2 changes: 1 addition & 1 deletion agents/templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ templates/
## Usage

Templates are referenced by workflows. See:
- [create-admin-ui](../workflows/create-admin-ui/) - Full CRUD admin interface
- [create-admin-ui](../workflows/create-admin-ui.md) - Full CRUD admin interface

Each template file contains:
1. Location path for the new file
Expand Down
18 changes: 9 additions & 9 deletions agents/workflows/create-admin-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ Templates are located in `agents/templates/` for reuse across workflows.

| Template | Location | Description |
|----------|----------|-------------|
| [Model](../../templates/backend/model.md) | `api/src/models/` | Sequelize model with scopes |
| [Controller](../../templates/backend/controller.md) | `api/src/controllers/` | CRUD endpoints |
| [Policy](../../templates/backend/policy.md) | `api/src/policies/` | Authorization rules |
| [Services](../../templates/backend/services.md) | `api/src/services/{resources}/` | Create, Update, Destroy |
| [Serializers](../../templates/backend/serializers.md) | `api/src/serializers/{resources}/` | Index, Show, Reference |
| [Model](../templates/backend/model.md) | `api/src/models/` | Sequelize model with scopes |
| [Controller](../templates/backend/controller.md) | `api/src/controllers/` | CRUD endpoints |
| [Policy](../templates/backend/policy.md) | `api/src/policies/` | Authorization rules |
| [Services](../templates/backend/services.md) | `api/src/services/{resources}/` | Create, Update, Destroy |
| [Serializers](../templates/backend/serializers.md) | `api/src/serializers/{resources}/` | Index, Show, Reference |

**Integration Points:**
- `api/src/controllers/index.ts` - Export controller
Expand All @@ -52,10 +52,10 @@ Templates are located in `agents/templates/` for reuse across workflows.

| Template | Location | Description |
|----------|----------|-------------|
| [API Client](../../templates/frontend/api-client.md) | `web/src/api/` | Type-safe HTTP client |
| [Composables](../../templates/frontend/composables.md) | `web/src/use/` | Reactive data fetching |
| [Components](../../templates/frontend/components.md) | `web/src/components/{resources}/` | DataTable, Forms, UniqueTextField |
| [Pages](../../templates/frontend/pages.md) | `web/src/pages/admin/{resources}/` | List, New, Edit pages |
| [API Client](../templates/frontend/api-client.md) | `web/src/api/` | Type-safe HTTP client |
| [Composables](../templates/frontend/composables.md) | `web/src/use/` | Reactive data fetching |
| [Components](../templates/frontend/components.md) | `web/src/components/{resources}/` | DataTable, Forms, UniqueTextField |
| [Pages](../templates/frontend/pages.md) | `web/src/pages/admin/{resources}/` | List, New, Edit pages |

**Integration Points:**
- `web/src/routes.ts` - Add routes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export type InformationSharingAgreementAsConfidentialityAcknowledgement = {
"access_level.is_internal": boolean
"access_level.is_protected_and_limited": boolean
"access_level.is_confidential_and_restricted": boolean
access_level_department_restriction: string
department_branch_unit_hierarchy: string
has_additional_access_restrictions: boolean
additional_access_restrictions: string
Expand Down Expand Up @@ -128,6 +129,7 @@ export class CreateSerializer extends BaseSerializer<InformationSharingAgreement
"access_level.is_internal": isInternal,
"access_level.is_protected_and_limited": isProtectedAndLimited,
"access_level.is_confidential_and_restricted": isConfidentialAndRestricted,
access_level_department_restriction: this.record.accessLevelDepartmentRestriction ?? "",
department_branch_unit_hierarchy: departmentBranchUnitHierarchy,
has_additional_access_restrictions: this.record.hasAdditionalAccessRestrictions ?? false,
additional_access_restrictions: this.record.additionalAccessRestrictions ?? "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ import { isEmpty, isNil } from "lodash"

import db, {
ArchiveItem,
ArchiveItemCategory,
ExternalOrganization,
InformationSharingAgreement,
InformationSharingAgreementArchiveItem,
User,
} from "@/models"
import BaseService from "@/services/base-service"
import { ArchiveItemFiles } from "@/services"

export type ArchiveItemCategoriesAttributes = {
categoryId: number
const ACCESS_LEVEL_TO_SECURITY_LEVEL: Record<string, number> = {
[InformationSharingAgreement.AccessLevels.INTERNAL]: ArchiveItem.Levels.LOW,
[InformationSharingAgreement.AccessLevels.PROTECTED_AND_LIMITED]: ArchiveItem.Levels.MEDIUM,
[InformationSharingAgreement.AccessLevels.CONFIDENTIAL_AND_RESTRICTED]: ArchiveItem.Levels.HIGH,
}

export type ArchiveItemFilesAttributes = {
Expand All @@ -21,7 +23,6 @@ export type ArchiveItemFilesAttributes = {
}

export type ArchiveItemCreationAttributes = Partial<CreationAttributes<ArchiveItem>> & {
archiveItemCategoriesAttributes?: ArchiveItemCategoriesAttributes[]
archiveItemFilesAttributes?: ArchiveItemFilesAttributes[]
}

Expand All @@ -35,41 +36,36 @@ export class CreateService extends BaseService {
}

async perform(): Promise<ArchiveItem> {
const {
title,
status,
isDecision,
confidentialityReceipt,
securityLevel,
archiveItemCategoriesAttributes,
archiveItemFilesAttributes,
...optionalAttributes
} = this.attributes

if (isNil(title) || isEmpty(title)) {
throw new Error("Title is required")
}
const { confidentialityReceipt, archiveItemFilesAttributes, ...optionalAttributes } =
this.attributes

if (isNil(confidentialityReceipt) || confidentialityReceipt !== true) {
throw new Error("Confidentiality receipt is required, and must be true")
}

if (isNil(securityLevel)) {
throw new Error("Security level is required")
const { title, purpose, authorizedApplication, accessLevel, externalGroupContactId } =
this.informationSharingAgreement

if (isNil(title) || isEmpty(title)) {
throw new Error("Title is required")
}

// TODO: remove these from the model if they are unused by the UI.
const isDecisionOrFallback = isDecision ?? false
const statusOrFallback = status ?? ArchiveItem.Statuses.ACCEPTED
const accessLevelOrDefault = accessLevel ?? InformationSharingAgreement.AccessLevels.INTERNAL
const securityLevel = ACCESS_LEVEL_TO_SECURITY_LEVEL[accessLevelOrDefault]

const yukonFirstNations = await this.resolveYukonFirstNations(externalGroupContactId)

return db.transaction(async () => {
const archiveItem = await ArchiveItem.create({
...optionalAttributes,
title,
confidentialityReceipt,
isDecision: isDecisionOrFallback,
status: statusOrFallback,
isDecision: false,
status: ArchiveItem.Statuses.ACCEPTED,
securityLevel,
sharingPurpose: authorizedApplication,
description: purpose,
yukonFirstNations,
userId: this.currentUser.id,
})

Expand All @@ -79,8 +75,6 @@ export class CreateService extends BaseService {
await this.uploadFilesForArchiveItem(archiveItem.id, archiveItemFilesAttributes)
}

await this.assignCategoriesToArchiveItem(archiveItem.id, archiveItemCategoriesAttributes)

return archiveItem.reload({
include: ["categories", "accessGrants", "user"],
})
Expand All @@ -104,21 +98,29 @@ export class CreateService extends BaseService {
})
}

private async assignCategoriesToArchiveItem(
archiveItemId: number,
archiveItemCategoriesAttributes: { categoryId: number }[] | undefined
): Promise<void> {
if (isNil(archiveItemCategoriesAttributes) || isEmpty(archiveItemCategoriesAttributes)) {
return
private async resolveYukonFirstNations(
externalGroupContactId: number | null
): Promise<string[] | null> {
if (isNil(externalGroupContactId)) return null

const organization = await ExternalOrganization.findOne({
include: [
{
association: "users",
attributes: [],
where: {
id: externalGroupContactId,
},
},
],
})

if (isNil(organization)) {
throw new Error("External group contact is missing its associated external organization")
}

const archiveItemCategoriesAttributesWithArchiveItemId = archiveItemCategoriesAttributes.map(
({ categoryId }) => ({
archiveItemId,
categoryId,
})
)
await ArchiveItemCategory.bulkCreate(archiveItemCategoriesAttributesWithArchiveItemId)
const { name } = organization
return [name]
}
}

Expand Down
2 changes: 1 addition & 1 deletion bin/open-in-editor-bridge.rb
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def shutdown

return unless pid

Process.kill("TERM", pid)
Process.kill("TERM", -pid)
delete_pid_file

puts "Stopped editor bridge."
Expand Down
11 changes: 0 additions & 11 deletions web/src/api/information-sharing-agreements/archive-items-api.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
import http from "@/api/http-client"
import { type ArchiveItemAsShow } from "@/api/archive-items-api"
import { SecurityLevel } from "@/api/archive-items-api"

export type ArchiveItemCreationAttributes = {
title: string
description: string | null
sharingPurpose: string | null
confidentialityReceipt: boolean
yukonFirstNations: string[]
securityLevel: SecurityLevel
tags: string[]
} & {
archiveItemCategoriesAttributes: {
categoryId: number
}[]
}

export const archiveItemsApi = {
Expand Down
23 changes: 0 additions & 23 deletions web/src/components/archive-items/ArchiveItemNewButton.vue

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const router = useRouter()
function goToUserPage(userId: number) {
// TODO: standardize this route to redirect to user read page (once a read page exists)
return router.push({
name: "users/UserEditPage",
name: "users/UserInternalEditPage",
params: {
userId,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const router = useRouter()
function goToUserPage(userId: number) {
// TODO: standardize this route to redirect to user read page
return router.push({
name: "users/UserEditPage",
name: "users/UserInternalEditPage",
params: {
userId,
},
Expand Down
Loading