@mediamonks/canopy-cli 0.7.12 → 0.7.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{db-8Etjmzxh.mjs → db-DKnJQPm5.mjs} +2 -2
- package/dist/{deploy-B1WrPq5W.mjs → deploy-CnxJ4TE6.mjs} +2 -2
- package/dist/dev-BqLvttKc.mjs +2 -0
- package/dist/{dev-BnUYGQQm.mjs → dev-CyJT6EfQ.mjs} +4 -4
- package/dist/docs/ci.md +50 -0
- package/dist/docs/cli-create.md +46 -0
- package/dist/docs/cli-db.md +86 -0
- package/dist/docs/cli-delete.md +44 -0
- package/dist/docs/cli-deploy.md +58 -0
- package/dist/docs/cli-dev.md +82 -0
- package/dist/docs/cli-docs.md +47 -0
- package/dist/docs/cli-download.md +42 -0
- package/dist/docs/cli-egress.md +37 -0
- package/dist/docs/cli-feedback.md +85 -0
- package/dist/docs/cli-index.md +61 -0
- package/dist/docs/cli-init.md +46 -0
- package/dist/docs/cli-login.md +43 -0
- package/dist/docs/cli-logout.md +32 -0
- package/dist/docs/cli-logs.md +57 -0
- package/dist/docs/cli-open.md +41 -0
- package/dist/docs/cli-projects.md +43 -0
- package/dist/docs/cli-promote.md +44 -0
- package/dist/docs/cli-rollback.md +45 -0
- package/dist/docs/cli-skill.md +39 -0
- package/dist/docs/cli-staging.md +54 -0
- package/dist/docs/cli-token.md +47 -0
- package/dist/docs/cli-upgrade.md +43 -0
- package/dist/docs/cli-usage.md +43 -0
- package/dist/docs/cli-whoami.md +46 -0
- package/dist/docs/cli.md +86 -0
- package/dist/docs/data.md +85 -0
- package/dist/docs/deploy.md +81 -0
- package/dist/docs/dev.md +72 -0
- package/dist/docs/developers-agents-and-ai.md +95 -0
- package/dist/docs/developers-architecture.md +106 -0
- package/dist/docs/getting-started.md +108 -0
- package/dist/docs/index.json +336 -0
- package/dist/docs/infrastructure.md +406 -0
- package/dist/docs/migrations.md +183 -0
- package/dist/docs/overview-faq.md +105 -0
- package/dist/docs/overview-how-it-works.md +82 -0
- package/dist/docs/overview-use-cases.md +76 -0
- package/dist/docs/overview-what-is-canopy.md +75 -0
- package/dist/docs/platform-ai-usage.md +65 -0
- package/dist/docs/platform-client-access.md +54 -0
- package/dist/docs/platform-deploys-and-rollbacks.md +93 -0
- package/dist/docs/platform-egress.md +75 -0
- package/dist/docs/platform-feedback.md +119 -0
- package/dist/docs/platform-google.md +213 -0
- package/dist/docs/platform-members-and-access.md +71 -0
- package/dist/docs/platform-project-data.md +76 -0
- package/dist/docs/platform-schedules.md +90 -0
- package/dist/docs/platform-sites-and-profiles.md +61 -0
- package/dist/docs/porting-nextjs.md +233 -0
- package/dist/docs/sdk-ai.md +103 -0
- package/dist/docs/sdk-auth.md +57 -0
- package/dist/docs/sdk-database.md +126 -0
- package/dist/docs/sdk-files.md +82 -0
- package/dist/docs/sdk-services.md +58 -0
- package/dist/docs/sdk.md +126 -0
- package/dist/docs/staging.md +106 -0
- package/dist/docs/static-serving.md +323 -0
- package/dist/docs/troubleshooting.md +102 -0
- package/dist/{docs-DxB7NhZs.mjs → docs-3pQHiuTn.mjs} +2 -2
- package/dist/{egress-CN_axsAN.mjs → egress-BFSwa8Uu.mjs} +1 -1
- package/dist/{feedback-B-GXUBPs.mjs → feedback-DReTDDzD.mjs} +26 -7
- package/dist/index.mjs +25 -24
- package/dist/{local-BGRd_FMZ.mjs → local-BQxsp-ZQ.mjs} +2 -2
- package/dist/{login-D7dI8D9N.mjs → login-BDTO3nVw.mjs} +1 -1
- package/dist/{logs-DNiZquki.mjs → logs-C53y2eAS.mjs} +1 -1
- package/dist/{migrations-C-5x6SYf.mjs → migrations-C6EcKD6a.mjs} +1 -1
- package/dist/{open-DRPp4QJg.mjs → open-C5x3tX6I.mjs} +1 -1
- package/dist/{package-CDLufecy.mjs → package-CuyFMXam.mjs} +1 -1
- package/dist/{projects-C6JQjVqg.mjs → projects-MMbv7MmK.mjs} +1 -1
- package/dist/schedule-Cq9K0rnE.mjs +106 -0
- package/dist/skill/canopy/SKILL.md +160 -0
- package/dist/{skill-BOWfqwr2.mjs → skill-M4RHvuUB.mjs} +2 -2
- package/dist/{staging-Bw1D_J8M.mjs → staging-D8G4amjO.mjs} +1 -1
- package/dist/templates/spa/.github/workflows/canopy-deploy.yml +34 -0
- package/dist/templates/spa/AGENTS.md +47 -0
- package/dist/templates/spa/README.md +14 -0
- package/dist/templates/spa/_gitignore +4 -0
- package/dist/templates/spa/canopy.json +5 -0
- package/dist/templates/spa/index.html +12 -0
- package/dist/templates/spa/package.json +21 -0
- package/dist/templates/spa/src/app.tsx +25 -0
- package/dist/templates/spa/src/canopy.ts +5 -0
- package/dist/templates/spa/src/main.tsx +10 -0
- package/dist/templates/spa/src/style.css +29 -0
- package/dist/templates/spa/tsconfig.json +16 -0
- package/dist/templates/spa/vite.config.ts +7 -0
- package/dist/templates/static/AGENTS.md +45 -0
- package/dist/templates/static/README.md +9 -0
- package/dist/templates/static/_gitignore +2 -0
- package/dist/templates/static/canopy.json +4 -0
- package/dist/templates/static/index.html +21 -0
- package/dist/templates/static/main.js +9 -0
- package/dist/templates/static/style.css +29 -0
- package/dist/templates/worker/.dev.vars.example +9 -0
- package/dist/templates/worker/.github/workflows/canopy-deploy.yml +34 -0
- package/dist/templates/worker/AGENTS.md +63 -0
- package/dist/templates/worker/README.md +17 -0
- package/dist/templates/worker/_gitignore +5 -0
- package/dist/templates/worker/canopy.json +6 -0
- package/dist/templates/worker/index.html +12 -0
- package/dist/templates/worker/package.json +22 -0
- package/dist/templates/worker/src/app.tsx +25 -0
- package/dist/templates/worker/src/canopy.ts +5 -0
- package/dist/templates/worker/src/main.tsx +10 -0
- package/dist/templates/worker/src/style.css +29 -0
- package/dist/templates/worker/tsconfig.json +16 -0
- package/dist/templates/worker/vite.config.ts +7 -0
- package/dist/templates/worker/worker/index.ts +52 -0
- package/dist/{token-D7zrIF8G.mjs → token-BUxgRJVA.mjs} +1 -1
- package/dist/{ui-2mrJcjYC.mjs → ui-B1Px5y7q.mjs} +17 -0
- package/dist/{upgrade-fhfrid_O.mjs → upgrade-C8Xox-P-.mjs} +2 -2
- package/dist/{usage-CX1Izj_l.mjs → usage-DjNngyvy.mjs} +1 -1
- package/package.json +1 -1
- package/dist/dev-CySBxW7I.mjs +0 -2
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Feedback & bug reports
|
|
3
|
+
description: A built-in feedback widget on every project, a ticket-lite inbox behind it, and a CLI that lets agents work the backlog.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Every Canopy project gets an in-app feedback channel without writing a line of
|
|
7
|
+
code: signed-in Monks see a small floating button on the live app, pick **Bug**
|
|
8
|
+
or **Feedback**, type what happened, and send. The report lands in the
|
|
9
|
+
project's **Feedback tab** on the dashboard, with everything an investigator
|
|
10
|
+
needs captured automatically — page URL, the deploy version that served it,
|
|
11
|
+
viewport, and recent console errors.
|
|
12
|
+
|
|
13
|
+
It is deliberately **not** a ticketing product: an item has a status, an
|
|
14
|
+
append-only comment trail, and nothing else. No assignees, priorities, or
|
|
15
|
+
boards.
|
|
16
|
+
|
|
17
|
+
## The widget
|
|
18
|
+
|
|
19
|
+
- Appears only for **signed-in Monks**. Client-password visitors never see it —
|
|
20
|
+
the platform doesn't even send them the script.
|
|
21
|
+
- On by default for every project. Turn it off per project in
|
|
22
|
+
**Settings → Feedback widget**; the change applies on the next page load.
|
|
23
|
+
- Submissions are always identified (your company sign-in), so there's no
|
|
24
|
+
anonymous spam and no reporter field to fill in.
|
|
25
|
+
- The widget also shows your own previous reports for that project with their
|
|
26
|
+
current status.
|
|
27
|
+
- A page can reshape the chooser with meta tags — this docs site does exactly
|
|
28
|
+
that: `<meta name="canopy-feedback-kinds" content="docs,feedback">` swaps
|
|
29
|
+
"Bug" for "Docs issue", and `canopy-feedback-prompt` replaces the textarea
|
|
30
|
+
placeholder. Kinds are limited to `bug`, `feedback`, `docs`.
|
|
31
|
+
|
|
32
|
+
## Screenshots
|
|
33
|
+
|
|
34
|
+
A screenshot is often the whole report, so you can attach up to six to any
|
|
35
|
+
report:
|
|
36
|
+
|
|
37
|
+
- **In the widget:** click **Attach screenshot**, or paste one straight from
|
|
38
|
+
the clipboard into the message box, or drop an image on the panel. Thumbnails
|
|
39
|
+
show what will be sent, and each one can be removed before you hit Send.
|
|
40
|
+
- **On the dashboard:** the same three ways, from the report itself — so you can
|
|
41
|
+
add a picture to a report after filing it, or to a comment as you write it
|
|
42
|
+
("here's what it looks like after the fix"). Click any thumbnail for the full
|
|
43
|
+
image, then use the arrow keys to page through the rest.
|
|
44
|
+
- **From the CLI:** `canopy feedback report "…" --attach ./shot.png`, or
|
|
45
|
+
`canopy feedback attach <id> ./after-fix.png` for a report that already
|
|
46
|
+
exists. `canopy feedback show <id> --download <dir>` saves a report's
|
|
47
|
+
screenshots so an agent can look at them.
|
|
48
|
+
|
|
49
|
+
PNG, JPEG, WebP and GIF, up to 5 MB each. Large screenshots are scaled down in
|
|
50
|
+
your browser before they're sent, so a full-screen retina capture goes up small
|
|
51
|
+
without you doing anything. Screenshots are visible to the same people as the
|
|
52
|
+
report itself, and are deleted with it.
|
|
53
|
+
|
|
54
|
+
## The inbox
|
|
55
|
+
|
|
56
|
+
Project members triage reports on the **Feedback tab**:
|
|
57
|
+
|
|
58
|
+
- Statuses: `investigate → investigated → accepted → in_progress → resolved`,
|
|
59
|
+
plus `declined`.
|
|
60
|
+
- Everything arrives as **investigate** — nobody has looked at it yet. An agent
|
|
61
|
+
can pick those up, work out what is actually going on, and write the findings
|
|
62
|
+
on the report as **investigated**.
|
|
63
|
+
- **`accepted` means a person said "build this."** It is the one status an
|
|
64
|
+
agent should never reach for on its own.
|
|
65
|
+
- The order is a suggestion, not a track. Accept something straight away, skip
|
|
66
|
+
the investigation, or decline it at any point.
|
|
67
|
+
- Every status change and comment is recorded on the item's trail.
|
|
68
|
+
- A comment can be marked **internal** (the toggle next to the comment box):
|
|
69
|
+
visible to project members and admins only, never the reporter. That's the
|
|
70
|
+
place for stack traces, query plans, and other working notes that would only
|
|
71
|
+
confuse the person who filed the report — screenshots attached to an
|
|
72
|
+
internal note stay internal too.
|
|
73
|
+
- Reporters follow their submissions on the **Reports page** (dashboard
|
|
74
|
+
header) and can comment on or withdraw their own items; only project
|
|
75
|
+
members change statuses.
|
|
76
|
+
|
|
77
|
+
## Working the backlog with an agent
|
|
78
|
+
|
|
79
|
+
Because the CLI exposes the inbox, "look into the new reports" and "work
|
|
80
|
+
through the accepted feedback" are both prompts, not processes:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
canopy feedback list --status investigate # what nobody has looked at yet
|
|
84
|
+
canopy feedback show <id> # body + captured context + trail
|
|
85
|
+
canopy feedback status <id> investigated \
|
|
86
|
+
--comment "root cause: the upload grant expires too early"
|
|
87
|
+
canopy feedback list --status accepted # what a person asked for
|
|
88
|
+
canopy feedback status <id> resolved --comment "fixed in v42"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`investigated` always carries the findings — the note is required, because a
|
|
92
|
+
report that claims someone looked into it and shows nothing is worse than an
|
|
93
|
+
untouched one. Then it waits: **accepting is the person's call**, so an agent
|
|
94
|
+
sets `accepted` only when the person it is working with says to build the
|
|
95
|
+
thing.
|
|
96
|
+
|
|
97
|
+
`show` includes the deploy version that served the page when the bug was
|
|
98
|
+
reported — reproduce against that, not whatever is live now. A report worth
|
|
99
|
+
pushing back on gets `status <id> declined` with a comment saying why.
|
|
100
|
+
|
|
101
|
+
## Reporting problems with Canopy itself
|
|
102
|
+
|
|
103
|
+
When a `canopy` command fails while you (or your agent) are building a
|
|
104
|
+
project, file it against the **platform inbox** — not your own project:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
canopy feedback report "deploy failed after upload" \
|
|
108
|
+
--command "canopy deploy --staging" --error "upload_grant_expired …"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
With no `--project`, the report goes to the platform team automatically, with
|
|
112
|
+
your CLI version, site, and the project you were working on attached. Before
|
|
113
|
+
filing: rule out user error first (`canopy docs troubleshooting`,
|
|
114
|
+
`vp env doctor` for toolchain issues), and skim `canopy feedback mine` to
|
|
115
|
+
avoid filing the same issue twice.
|
|
116
|
+
|
|
117
|
+
## CLI reference
|
|
118
|
+
|
|
119
|
+
See [canopy feedback](https://docs.canopy.website/cli/feedback) for every subcommand and flag.
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Google
|
|
3
|
+
description: Let your project work with Google data — Sheets, Docs, Calendar, Drive, Gmail — without handling any OAuth yourself.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Your project can work with Google data in two different ways, and the
|
|
7
|
+
difference matters: as **the project's own account**, or as **each visitor's
|
|
8
|
+
own account**.
|
|
9
|
+
|
|
10
|
+
Either way there is no OAuth setup to do. No Cloud project, no consent screen,
|
|
11
|
+
no client ID or secret, no redirect URLs, no tokens to store or refresh. Canopy
|
|
12
|
+
holds all of that.
|
|
13
|
+
|
|
14
|
+
## The project's own account
|
|
15
|
+
|
|
16
|
+
The owner connects one Google account on the project's **Services** tab and
|
|
17
|
+
picks what it may do. Everything the project sends to Google then happens as
|
|
18
|
+
that account — including scheduled jobs that run when nobody is signed in. A
|
|
19
|
+
shared team account is usually a better choice than a personal one.
|
|
20
|
+
|
|
21
|
+
This account is **only usable from your backend code**:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// in your worker
|
|
25
|
+
const doc = await canopy.google.project().fetch("https://docs.googleapis.com/v1/documents/<id>");
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Pages cannot use it at all. That is deliberate: it is one person's real
|
|
29
|
+
account, and anything a page can call, any visitor can call from their browser
|
|
30
|
+
console. When your pages need something from it, put a route in your backend
|
|
31
|
+
that returns just that — you decide what to expose.
|
|
32
|
+
|
|
33
|
+
> **Note:** Only the project owner can connect or disconnect this account.
|
|
34
|
+
|
|
35
|
+
## Each visitor's own account
|
|
36
|
+
|
|
37
|
+
Visitors can connect their own Google account to your project, and your pages
|
|
38
|
+
can then work with _their_ data — their calendar, their documents. They consent
|
|
39
|
+
themselves, and it only ever acts as them.
|
|
40
|
+
|
|
41
|
+
First, on the **Services** tab, tick what your app is allowed to ask visitors
|
|
42
|
+
for. Your app can never request more than that.
|
|
43
|
+
|
|
44
|
+
Then, from your pages:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
const google = canopy.google.user();
|
|
48
|
+
|
|
49
|
+
// On load: has this visitor connected, and what came back from a connect?
|
|
50
|
+
const result = google.consumeConnectResult(); // toast this, if not null
|
|
51
|
+
const status = await google.status();
|
|
52
|
+
|
|
53
|
+
if (!status.connected) {
|
|
54
|
+
// A full-page trip to Google, then straight back to this page.
|
|
55
|
+
google.connect(["calendar"]);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const events = await google.fetch(
|
|
59
|
+
"https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
60
|
+
);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`connect()` leaves the page, so put the button somewhere without unsaved work.
|
|
64
|
+
When the visitor comes back, `status()` is the reliable answer to "are they
|
|
65
|
+
connected" — `consumeConnectResult()` just tells you how the trip that _just_
|
|
66
|
+
happened went, so you can show a message.
|
|
67
|
+
|
|
68
|
+
Google asks the visitor for exactly the permissions you passed. Nothing your
|
|
69
|
+
project holds elsewhere carries over into what they see.
|
|
70
|
+
|
|
71
|
+
Your backend can use a visitor's connection too, while handling that visitor's
|
|
72
|
+
request — same `canopy.google.user()`, same account. It cannot in a scheduled
|
|
73
|
+
job, because then nobody is signed in.
|
|
74
|
+
|
|
75
|
+
> **Note:** Visitors need a Monks account to connect. People visiting with a project password cannot connect
|
|
76
|
+
> their own Google account.
|
|
77
|
+
|
|
78
|
+
## What a connection can reach
|
|
79
|
+
|
|
80
|
+
Permissions are grouped by product — Sheets, Docs, Slides, Calendar, Drive,
|
|
81
|
+
Gmail, Directory, Tasks, Forms, Meet — and most come in a reading and a
|
|
82
|
+
read-and-write form. Pick the narrowest that does the job: a page that shows a
|
|
83
|
+
spreadsheet wants **read spreadsheets**, not read and write.
|
|
84
|
+
|
|
85
|
+
A few are narrower than they first look, and are usually the right answer —
|
|
86
|
+
the full list is below:
|
|
87
|
+
|
|
88
|
+
| Instead of | Consider |
|
|
89
|
+
| ------------------------ | ------------------------------------------------------------------------------------------ |
|
|
90
|
+
| Read and write events | **Availability only** — find free slots without seeing what any meeting is |
|
|
91
|
+
| Read and write events | **Its own calendar** — a separate calendar your project owns, never touching the account's |
|
|
92
|
+
| Files this project makes | **Its own config folder** — a hidden folder nothing else can see |
|
|
93
|
+
|
|
94
|
+
A call to anything that wasn't ticked is refused before it reaches Google, and
|
|
95
|
+
so is a write using a reading-only permission.
|
|
96
|
+
|
|
97
|
+
Drive is deliberately limited to files your project created or that someone
|
|
98
|
+
explicitly opened with it — connecting Drive does not expose a whole Drive.
|
|
99
|
+
|
|
100
|
+
### Wider permissions
|
|
101
|
+
|
|
102
|
+
A few permissions read broadly across an account — a whole mailbox, meeting
|
|
103
|
+
recordings. Those are switched off until a Canopy admin unlocks them for your
|
|
104
|
+
project, and the picker shows them greyed out with the reason. Ask if you need
|
|
105
|
+
one. Others are listed as _under consideration_: they exist, we haven't opened
|
|
106
|
+
them yet.
|
|
107
|
+
|
|
108
|
+
## Every permission
|
|
109
|
+
|
|
110
|
+
Grouped the way the picker groups them. Pick the narrowest row that does
|
|
111
|
+
the job — most products offer a reading-only version, and a write using a
|
|
112
|
+
reading-only permission is refused before it reaches Google.
|
|
113
|
+
|
|
114
|
+
**Sheets**
|
|
115
|
+
|
|
116
|
+
| Permission | What it allows |
|
|
117
|
+
| --------------------------- | ----------------------------------------------------------- |
|
|
118
|
+
| Read spreadsheets | Read spreadsheets the account can open. Cannot change them. |
|
|
119
|
+
| Read and write spreadsheets | Read and change spreadsheets the account can open. |
|
|
120
|
+
|
|
121
|
+
**Docs**
|
|
122
|
+
|
|
123
|
+
| Permission | What it allows |
|
|
124
|
+
| ------------------------ | -------------------------------------------------------- |
|
|
125
|
+
| Read documents | Read documents the account can open. Cannot change them. |
|
|
126
|
+
| Read and write documents | Read and change documents the account can open. |
|
|
127
|
+
|
|
128
|
+
**Slides**
|
|
129
|
+
|
|
130
|
+
| Permission | What it allows |
|
|
131
|
+
| ---------------------------- | ------------------------------------------------------------ |
|
|
132
|
+
| Read presentations | Read presentations the account can open. Cannot change them. |
|
|
133
|
+
| Read and write presentations | Build and change presentations the account can open. |
|
|
134
|
+
|
|
135
|
+
**Calendar**
|
|
136
|
+
|
|
137
|
+
| Permission | What it allows |
|
|
138
|
+
| -------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
139
|
+
| Availability only | See when the account is free or busy, never what the meetings are. |
|
|
140
|
+
| Read events | Read events on the account's calendars. Cannot change them. |
|
|
141
|
+
| Read and write events | Read and manage events on the account's calendars. |
|
|
142
|
+
| Its own calendar | A separate calendar this project creates and owns. Never touches the account's own. |
|
|
143
|
+
| Manage all calendars _(under consideration)_ | Full control of every calendar, including creating and deleting them. |
|
|
144
|
+
|
|
145
|
+
**Drive**
|
|
146
|
+
|
|
147
|
+
| Permission | What it allows |
|
|
148
|
+
| --------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
149
|
+
| Files this project makes | Create files, and reopen the ones this project made or someone picked for it. |
|
|
150
|
+
| Its own config folder | A hidden folder only this project can see. Invisible in the account's Drive. |
|
|
151
|
+
| Recordings and transcripts **(wider access)** | Read the recordings and transcripts Meet saved to Drive. |
|
|
152
|
+
| Read the whole Drive _(under consideration)_ | Read and download every file the account can see. |
|
|
153
|
+
| Read all file names _(under consideration)_ | Names and metadata of every file the account can see, without contents. |
|
|
154
|
+
| Full Drive access _(under consideration)_ | Read, change and delete every file the account can see. |
|
|
155
|
+
|
|
156
|
+
**Gmail**
|
|
157
|
+
|
|
158
|
+
| Permission | What it allows |
|
|
159
|
+
| ---------------------------------------------- | ---------------------------------------------------------------- |
|
|
160
|
+
| Send mail | Send mail as the account. Cannot read the mailbox. |
|
|
161
|
+
| Read mail **(wider access)** | Read the account's mail. Cannot send, change or delete anything. |
|
|
162
|
+
| Read and organise mail _(under consideration)_ | Read, label and archive mail. Cannot permanently delete. |
|
|
163
|
+
|
|
164
|
+
**Directory**
|
|
165
|
+
|
|
166
|
+
| Permission | What it allows |
|
|
167
|
+
| ------------------------------------------------- | -------------------------------------------------------------------- |
|
|
168
|
+
| Look people up | Search the organisation's directory for colleagues. |
|
|
169
|
+
| Read personal contacts | Read the account's own contacts. |
|
|
170
|
+
| Read org users and groups _(under consideration)_ | Admin view of every user and group. Only works for Workspace admins. |
|
|
171
|
+
|
|
172
|
+
**Tasks**
|
|
173
|
+
|
|
174
|
+
| Permission | What it allows |
|
|
175
|
+
| -------------------- | ---------------------------------- |
|
|
176
|
+
| Read tasks | Read the account's task lists. |
|
|
177
|
+
| Read and write tasks | Create, change and complete tasks. |
|
|
178
|
+
|
|
179
|
+
**Forms**
|
|
180
|
+
|
|
181
|
+
| Permission | What it allows |
|
|
182
|
+
| ------------------- | -------------------------------------------------------- |
|
|
183
|
+
| Read form structure | Read a form's questions and settings, not its responses. |
|
|
184
|
+
| Build forms | Create and change forms. |
|
|
185
|
+
| Read responses | Read what people submitted. Often personal information. |
|
|
186
|
+
|
|
187
|
+
**Meet**
|
|
188
|
+
|
|
189
|
+
| Permission | What it allows |
|
|
190
|
+
| --------------------------- | ---------------------------------------------------------- |
|
|
191
|
+
| Meetings this project makes | Create meeting links and read details of the ones it made. |
|
|
192
|
+
|
|
193
|
+
## When a connection stops working
|
|
194
|
+
|
|
195
|
+
Google grants end on their own sometimes: someone changes their password,
|
|
196
|
+
removes Canopy from their account permissions, or the connection sits unused
|
|
197
|
+
for six months. Calls then fail asking for a reconnect. For the project's
|
|
198
|
+
account, the owner reconnects on the Services tab; for a visitor's, show the
|
|
199
|
+
connect button again. Nothing else needs changing.
|
|
200
|
+
|
|
201
|
+
Disconnecting also tells Google the grant is over, so access stops immediately
|
|
202
|
+
rather than lingering. Visitors can drop their own connection with
|
|
203
|
+
`canopy.google.user().disconnect()`.
|
|
204
|
+
|
|
205
|
+
## Local development
|
|
206
|
+
|
|
207
|
+
`canopy dev` uses the real connections, so Google works the same on your
|
|
208
|
+
machine as in production — including with `--local`. There is nothing to set up
|
|
209
|
+
locally, and no localhost URLs to register.
|
|
210
|
+
|
|
211
|
+
Because it is real, calls in development touch real data. Sending mail really
|
|
212
|
+
sends it. If that matters, connect a test account on your project's staging
|
|
213
|
+
channel and develop against that.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Members & access
|
|
3
|
+
description: Everything on Canopy sits behind Monks sign-in. Collaborators manage a project; other Monks can view the live app — unless you tighten it.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Nothing on Canopy is reachable by the anonymous internet. Every project URL
|
|
7
|
+
and the dashboard itself sit behind Monks OneLogin — visitors sign in with
|
|
8
|
+
their company account before they see anything. On top of that wall, each
|
|
9
|
+
project has its own roster that decides who can _manage_ it and, optionally,
|
|
10
|
+
who can _view_ it.
|
|
11
|
+
|
|
12
|
+
## The default: any Monk can look, members can manage
|
|
13
|
+
|
|
14
|
+
Out of the box:
|
|
15
|
+
|
|
16
|
+
- **Any signed-in Monk** can open a project's live URL and see the app. The
|
|
17
|
+
project also appears in the company-wide list on the dashboard.
|
|
18
|
+
- **Only the project's members** (and platform admins) can open its
|
|
19
|
+
management pages — deploy history, data browser, usage, and settings.
|
|
20
|
+
|
|
21
|
+
That default fits most internal work: colleagues can try what you built, but
|
|
22
|
+
nobody outside the team can touch its data or settings.
|
|
23
|
+
|
|
24
|
+
## Roles
|
|
25
|
+
|
|
26
|
+
- **Owner** — the person who created the project. Owners govern it: they
|
|
27
|
+
invite and remove collaborators, change access settings, and can delete
|
|
28
|
+
the project.
|
|
29
|
+
- **Collaborator** — invited teammates. They can do day-to-day work — deploy,
|
|
30
|
+
roll back, browse and edit data, manage schedules and secrets — but not
|
|
31
|
+
delete the project or manage its roster.
|
|
32
|
+
- **Platform admin** — can manage any project from the dashboard. Admins keep
|
|
33
|
+
governance access, but they do not silently bypass a collaborators-only
|
|
34
|
+
live app (see below).
|
|
35
|
+
|
|
36
|
+
## Inviting collaborators
|
|
37
|
+
|
|
38
|
+
Open the project's **Settings** tab and use the **Collaborators** card. A
|
|
39
|
+
searchable people picker finds anyone who has signed in to Canopy; adding
|
|
40
|
+
them takes effect immediately. Owners (and admins) can also remove people
|
|
41
|
+
from the same card.
|
|
42
|
+
|
|
43
|
+
## Collaborators-only mode
|
|
44
|
+
|
|
45
|
+
Sometimes "any Monk can look" is too open — payroll prototypes, sensitive
|
|
46
|
+
client work, unfinished things you'd rather not demo by accident. Flip on
|
|
47
|
+
**Settings → Who at Monks can open it → Restrict to collaborators** and the
|
|
48
|
+
live app is limited to the project's roster:
|
|
49
|
+
|
|
50
|
+
- Other Monks who open the URL get a clear "limited to its collaborators"
|
|
51
|
+
page instead of the app.
|
|
52
|
+
- The project still appears in the company list — it isn't hidden, just
|
|
53
|
+
closed.
|
|
54
|
+
- Platform admins can still manage the project in the dashboard, but they
|
|
55
|
+
must add themselves as collaborators if they need to open the live app.
|
|
56
|
+
- [Client password access](https://docs.canopy.website/platform/client-access), if you've enabled
|
|
57
|
+
it, is unaffected — the two controls are independent.
|
|
58
|
+
|
|
59
|
+
Turning it off again is the same toggle.
|
|
60
|
+
|
|
61
|
+
> **Note:** Collaborators-only gates the **live app**. Management access (settings, data, deploys) is always
|
|
62
|
+
> members-only, regardless of this toggle.
|
|
63
|
+
|
|
64
|
+
## Platform admins and the Users page
|
|
65
|
+
|
|
66
|
+
Platform admins get an extra **Users** page in the dashboard listing everyone
|
|
67
|
+
on Canopy — name, email, and when they first signed in — with a one-click way
|
|
68
|
+
to grant or remove admin. Accounts are created automatically on first
|
|
69
|
+
OneLogin sign-in; there is nothing to provision.
|
|
70
|
+
|
|
71
|
+
- [Client access](https://docs.canopy.website/platform/client-access) — Share work-in-progress with clients who don't have a Monks account.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Project data
|
|
3
|
+
description: Every project gets its own private database and file storage — browse it in the dashboard, snapshot it before risky changes, and pull it locally.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Every Canopy project comes with its own private database and file storage,
|
|
7
|
+
created automatically the moment the project exists. There are no connection
|
|
8
|
+
strings to configure and no servers to run — your app reads and writes through
|
|
9
|
+
the Canopy SDK, and no other project can ever see your data.
|
|
10
|
+
|
|
11
|
+
## The Data tab and the data explorer
|
|
12
|
+
|
|
13
|
+
Open a project in the dashboard and the **Data** tab shows what your app has
|
|
14
|
+
stored — every collection and table at a glance — plus the door into the
|
|
15
|
+
**data explorer**, a full-page workspace for actually digging in:
|
|
16
|
+
|
|
17
|
+
- **Schema sidebar** — collections and tables, each expandable to its
|
|
18
|
+
columns (types, primary keys) and indexes.
|
|
19
|
+
- **Browse** — click any table or collection to page through it with real
|
|
20
|
+
totals, sort by any column, and stack filters (equals, contains,
|
|
21
|
+
comparisons, null checks) without writing SQL. Click a row for the full
|
|
22
|
+
record, JSON pretty-printed. Export the current page as CSV or JSON.
|
|
23
|
+
- **SQL console** — a real editor with syntax highlighting and autocomplete
|
|
24
|
+
fed by your schema. Run with <kbd>⌘⏎</kbd>, see row counts and timing,
|
|
25
|
+
recall earlier queries from history, and hit **Explain** to see the query
|
|
26
|
+
plan.
|
|
27
|
+
|
|
28
|
+
The console is **read-only by default** — the platform rejects anything but
|
|
29
|
+
reads until you flip the writes toggle, so exploring production data is safe
|
|
30
|
+
by design. The explorer is fixed to the channel (live or staging) you opened
|
|
31
|
+
it from; to look at the other one, go back to the Data tab and switch there.
|
|
32
|
+
|
|
33
|
+
The **Files** tab next to it lists the project's blob storage — the uploads
|
|
34
|
+
and files your app has saved.
|
|
35
|
+
|
|
36
|
+
## Snapshots and restores
|
|
37
|
+
|
|
38
|
+
The Data tab's **Data safety** card is your undo button for data:
|
|
39
|
+
|
|
40
|
+
- **Snapshot** stores a full dump of the database on the platform. Take one
|
|
41
|
+
before a risky change — a big import, a cleanup script, letting an agent
|
|
42
|
+
loose on production data.
|
|
43
|
+
- **Restore** replaces the project's current data with a snapshot. This is
|
|
44
|
+
destructive by design (that's the point), so the dashboard asks you to
|
|
45
|
+
confirm.
|
|
46
|
+
- **Export** downloads a dump to your machine.
|
|
47
|
+
|
|
48
|
+
Snapshots live server-side and stay available until you delete the project,
|
|
49
|
+
so you can restore from days ago, not just from your last session.
|
|
50
|
+
|
|
51
|
+
> **Warning:** Restoring replaces **all** current data with the snapshot's contents. Take a fresh snapshot first
|
|
52
|
+
> if there's anything recent you might want back.
|
|
53
|
+
|
|
54
|
+
## The same tools from the terminal
|
|
55
|
+
|
|
56
|
+
Everything above is also available to you (and your coding agent) via the CLI:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
canopy db pull # download a fresh SQL dump
|
|
60
|
+
canopy db snapshot # store a dump server-side
|
|
61
|
+
canopy db snapshots # list stored snapshots
|
|
62
|
+
canopy db restore # replace project data with a snapshot
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`canopy db pull` is also how you develop against realistic data: pull a dump,
|
|
66
|
+
then run `canopy dev --local --pull` for a throwaway sandbox seeded with it.
|
|
67
|
+
|
|
68
|
+
## Portable by default, SQL when you need it
|
|
69
|
+
|
|
70
|
+
The SDK's document API (`canopy.db.collection(...)`) behaves the same
|
|
71
|
+
everywhere Canopy runs. Raw SQL via `canopy.db.sql()` passes straight through
|
|
72
|
+
to the underlying database — SQLite on the Cloudflare sites, Postgres on the
|
|
73
|
+
GCP pilot — so anything that database supports works. Your code can ask
|
|
74
|
+
`canopy.db.dialect()` which one it's talking to.
|
|
75
|
+
|
|
76
|
+
- [Working with project data](https://docs.canopy.website/guides/data) — Collection naming rules, dialects and raw SQL, dumps, and restore workflows in depth.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Schedules
|
|
3
|
+
description: Run named cron jobs in your project's backend — configured in the dashboard, so you can change the cadence without redeploying.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Schedules let a project do things on a clock: send a daily digest, refresh a
|
|
7
|
+
cache every hour, tick a counter every minute. You define **named jobs** in
|
|
8
|
+
the dashboard, and the platform wakes your project's backend at the right
|
|
9
|
+
times — your code only decides what each job does.
|
|
10
|
+
|
|
11
|
+
> **Note:** Schedules need a project with a custom backend. Per-project backends run on the **main** site and
|
|
12
|
+
> the **GCP pilot** site. On sites without backend support the Schedules section doesn't appear in
|
|
13
|
+
> Settings, and the API answers `not_supported_on_target`.
|
|
14
|
+
|
|
15
|
+
## Defining a schedule
|
|
16
|
+
|
|
17
|
+
In the dashboard, open the project's **Settings → Schedules**. Each schedule
|
|
18
|
+
has:
|
|
19
|
+
|
|
20
|
+
- a **name** (like `daily-digest`) — this is what your code switches on;
|
|
21
|
+
- a **cron expression** — standard 5-field cron, always in **UTC**;
|
|
22
|
+
- an **enabled** toggle, so you can pause a job without deleting it.
|
|
23
|
+
|
|
24
|
+
A project can have up to **5 schedules**, and the shortest interval is one
|
|
25
|
+
minute. Each row also shows its last run and, if it failed, the error — so
|
|
26
|
+
you can see at a glance whether a job is healthy.
|
|
27
|
+
|
|
28
|
+
You can also trigger a schedule manually from the dashboard, which is the
|
|
29
|
+
quickest way to test a handler without waiting for the clock.
|
|
30
|
+
|
|
31
|
+
## Handling schedules in your code
|
|
32
|
+
|
|
33
|
+
Your project's worker exports a `scheduled` handler next to its normal
|
|
34
|
+
`fetch` handler, and switches on the job's name:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
export default {
|
|
38
|
+
async fetch(request, env, ctx) {
|
|
39
|
+
return app.fetch(request, env, ctx);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
async scheduled(event, env, ctx) {
|
|
43
|
+
switch (event.name) {
|
|
44
|
+
case "daily-digest":
|
|
45
|
+
await sendDigest(env);
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
console.warn("unknown schedule", event.name);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`event.name` is the name you gave the schedule in the dashboard, `event.cron`
|
|
55
|
+
is the expression that fired, and `event.scheduledTime` is when it fired.
|
|
56
|
+
Inside the handler your code has the same environment as an HTTP request —
|
|
57
|
+
secrets, the project database, and blob storage all work the same way.
|
|
58
|
+
|
|
59
|
+
## Data access without a signed-in user
|
|
60
|
+
|
|
61
|
+
A scheduled run has no browser session attached, but `canopy.db`, `canopy.blob`
|
|
62
|
+
and `canopy.ai` still work: the platform seals a **project-scoped worker
|
|
63
|
+
token** into your backend on every deploy, and calls through the platform
|
|
64
|
+
fall back to it whenever the request carries no user credential. You don't
|
|
65
|
+
configure or see this token — it's minted, rotated (every deploy replaces
|
|
66
|
+
it), and revoked with the project automatically, and it only ever reaches
|
|
67
|
+
your own project's data.
|
|
68
|
+
|
|
69
|
+
The one thing that behaves differently is identity: `canopy.auth.user()`
|
|
70
|
+
resolves with `kind: "worker"` and empty `id`/`email`/`name` — there is no
|
|
71
|
+
one signed in during a cron tick, and your code should treat that as "no
|
|
72
|
+
user", not as an error.
|
|
73
|
+
|
|
74
|
+
## Why the name matters
|
|
75
|
+
|
|
76
|
+
Switch on `event.name`, not on the cron string. The dashboard is the source
|
|
77
|
+
of truth for _when_ a job runs, so you can change `daily-digest` from 6:00 to
|
|
78
|
+
7:30 — or pause it — without touching code or redeploying. The name is the
|
|
79
|
+
stable contract between the dashboard and your handler.
|
|
80
|
+
|
|
81
|
+
## Things to know
|
|
82
|
+
|
|
83
|
+
- **Cron runs as the project, not as a person.** Data access works (see
|
|
84
|
+
above), but there is no signed-in user — `auth.user()` answers with
|
|
85
|
+
`kind: "worker"` and no identity.
|
|
86
|
+
- **All times are UTC.** `0 6 * * *` is 6:00 UTC, not local time.
|
|
87
|
+
- **Failures are visible.** A run that throws records its error on the
|
|
88
|
+
schedule row in Settings, so silent breakage doesn't stay silent.
|
|
89
|
+
|
|
90
|
+
- [Infrastructure](https://docs.canopy.website/guides/infrastructure) — What runs where — assets, backends, databases — across the Canopy sites.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Sites & profiles
|
|
3
|
+
description: Canopy runs as more than one installation. Most people only ever use main — here's what the others are and how the CLI keeps them straight.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Canopy isn't a single installation: the same platform runs as a few separate
|
|
7
|
+
**sites**, each with its own domain, its own projects, and its own data.
|
|
8
|
+
Unless someone told you otherwise, **you're on `main` and can stop reading
|
|
9
|
+
here** — the rest of this page explains what the other sites are for and how
|
|
10
|
+
the CLI targets them.
|
|
11
|
+
|
|
12
|
+
## The sites
|
|
13
|
+
|
|
14
|
+
| Site | Project URLs | What it's for |
|
|
15
|
+
| ----------- | --------------------- | ------------------------------------------------- |
|
|
16
|
+
| `main` | `*.canopy.website` | The real platform. Your projects live here. |
|
|
17
|
+
| `staging` | `*.thanarie.dev` | The platform team's testbed for platform changes. |
|
|
18
|
+
| `gcp-pilot` | `*.canopy.monks.zone` | A pilot running on Google Cloud. |
|
|
19
|
+
|
|
20
|
+
Sites are fully separate: a project on `main` doesn't exist on `staging`, and
|
|
21
|
+
signing in to one doesn't create anything on another. They can also differ in
|
|
22
|
+
what they support — the dashboard simply hides features a site can't honor,
|
|
23
|
+
and the API says `not_supported_on_target` if asked directly.
|
|
24
|
+
|
|
25
|
+
## What a profile is
|
|
26
|
+
|
|
27
|
+
A **profile** is the CLI's name for a site. `canopy login` signs you in once
|
|
28
|
+
via OneLogin and stores a credential for every site in one go; the profile
|
|
29
|
+
just picks which one a command talks to.
|
|
30
|
+
|
|
31
|
+
Three things decide the effective profile, in order:
|
|
32
|
+
|
|
33
|
+
1. `--profile <id>` on the command (or the `CANOPY_PROFILE` environment
|
|
34
|
+
variable) — one-off override.
|
|
35
|
+
2. The `"profile"` pinned in the project's `canopy.json` — set when the
|
|
36
|
+
project was created, so a checkout always targets the site it belongs to.
|
|
37
|
+
3. Your default active profile — `main` unless you chose otherwise at login.
|
|
38
|
+
|
|
39
|
+
Every command prints the site it's talking to in its header line, and
|
|
40
|
+
`canopy whoami` shows your email, active profile, and API host — so there's
|
|
41
|
+
never a mystery about where a deploy just went.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
canopy whoami # who am I, on which site?
|
|
45
|
+
canopy --profile gcp-pilot deploy # one command against the pilot
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## When you'd actually care
|
|
49
|
+
|
|
50
|
+
- **Never, usually.** Day-to-day work on your own projects is all `main`,
|
|
51
|
+
and the `canopy.json` pin keeps it that way without any flags.
|
|
52
|
+
- **Trying backend features.** Custom backends and
|
|
53
|
+
[schedules](https://docs.canopy.website/platform/schedules) currently run on `gcp-pilot`, so
|
|
54
|
+
experiments with those happen there.
|
|
55
|
+
- **Helping test platform changes.** If the platform team asks you to check
|
|
56
|
+
something on `staging`, `--profile staging` points any command at it.
|
|
57
|
+
|
|
58
|
+
> **Note:** Deploying to a different site publishes a **separate copy** of the project there — it doesn't move
|
|
59
|
+
> or mirror the one on `main`. Each site keeps its own versions, data, and members.
|
|
60
|
+
|
|
61
|
+
- [CLI reference](https://docs.canopy.website/guides/cli) — Every canopy command, including login, whoami, and the --profile flag.
|