@forgezero/runtime 0.1.19 → 0.1.21
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/notify-templates.js +25 -14
- package/dist/notify.d.ts +1 -0
- package/dist/notify.js +19 -10
- package/dist/schema-typebox.js +2 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.js +2 -0
- package/package.json +2 -2
package/dist/notify-templates.js
CHANGED
|
@@ -88,27 +88,36 @@ function createNotifier(options) {
|
|
|
88
88
|
}
|
|
89
89
|
function layout(args) {
|
|
90
90
|
const brand = escapeHtml(args.brand ?? "ForgeZero");
|
|
91
|
+
const preheader = escapeHtml(args.preheader ?? `${args.title} — secure account notification`);
|
|
91
92
|
return `<!doctype html>
|
|
92
|
-
<html><
|
|
93
|
-
<
|
|
93
|
+
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="dark"><meta name="supported-color-schemes" content="dark"></head>
|
|
94
|
+
<body style="margin:0;padding:0;background:#090b0e;color:#f4f5f7;font-family:Inter,ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;-webkit-text-size-adjust:100%">
|
|
95
|
+
<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;line-height:1px;font-size:1px">${preheader} ‌ ‌ ‌ ‌</div>
|
|
96
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="width:100%;background:#090b0e;padding:48px 16px">
|
|
94
97
|
<tr><td align="center">
|
|
95
|
-
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:
|
|
96
|
-
<tr><td style="
|
|
97
|
-
<
|
|
98
|
-
<
|
|
98
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:580px;border-collapse:separate;background:#15181d;border:1px solid #30353d;border-radius:18px;box-shadow:0 24px 72px rgba(0,0,0,.42);overflow:hidden">
|
|
99
|
+
<tr><td style="height:3px;background:linear-gradient(90deg,#ff7a1a 0%,#ffb25c 38%,#30353d 38%);border-radius:18px 18px 0 0;font-size:0;line-height:0"> </td></tr>
|
|
100
|
+
<tr><td style="padding:28px 32px 12px">
|
|
101
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0"><tr>
|
|
102
|
+
<td valign="middle"><table role="presentation" cellpadding="0" cellspacing="0"><tr><td style="width:34px;height:34px;border:1px solid #5b3822;border-radius:10px;background:#20150e;text-align:center;color:#ff8b3d;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:16px;font-weight:800">FZ</td><td style="padding-left:11px;font-size:13px;font-weight:750;letter-spacing:.11em;text-transform:uppercase;color:#f4f5f7">${brand}</td></tr></table></td>
|
|
103
|
+
<td align="right" valign="middle"><span style="display:inline-block;padding:5px 8px;border:1px solid #394049;border-radius:999px;color:#9da5b2;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px;font-weight:700;letter-spacing:.1em;text-transform:uppercase">Protected message</span></td>
|
|
104
|
+
</tr></table>
|
|
105
|
+
<div style="margin-top:30px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:#ff8b3d">Account security</div>
|
|
106
|
+
<h1 style="margin:9px 0 0;font-size:26px;line-height:1.22;font-weight:700;letter-spacing:-.025em;color:#f7f8fa">${args.title}</h1>
|
|
99
107
|
</td></tr>
|
|
100
|
-
<tr><td style="padding:
|
|
108
|
+
<tr><td style="padding:14px 32px 30px;font-size:15px;line-height:1.65;color:#c8cdd6">${args.body}</td></tr>
|
|
109
|
+
<tr><td style="padding:15px 32px;border-top:1px solid #2a2f36;background:#111419;color:#7f8793;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;line-height:1.5;letter-spacing:.06em;text-transform:uppercase">Encrypted transport · Request-bound verification · No password</td></tr>
|
|
101
110
|
</table>
|
|
102
|
-
${args.footer ? `<
|
|
111
|
+
${args.footer ? `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:580px"><tr><td style="padding:20px 18px 0;text-align:center;font-size:12px;line-height:1.6;color:#747c89">${args.footer}<br><span style="display:inline-block;margin-top:5px;color:#505762">ForgeZero · secure infrastructure control plane</span></td></tr></table>` : ""}
|
|
103
112
|
</td></tr></table>
|
|
104
113
|
</body></html>`;
|
|
105
114
|
}
|
|
106
|
-
var codeBlock = (code) => `<div style="margin:
|
|
107
|
-
var button = (label, href) => `<div style="margin:
|
|
115
|
+
var codeBlock = (code) => `<div style="margin:24px 0;padding:22px 16px;background:#0b0d10;border:1px solid #3b414b;border-radius:12px;text-align:center;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:32px;line-height:1;font-weight:750;letter-spacing:.32em;color:#ffffff;box-shadow:inset 3px 0 0 #ff7a1a,0 10px 28px rgba(0,0,0,.22)">${code}</div>`;
|
|
116
|
+
var button = (label, href) => `<div style="margin:26px 0"><a href="${href}" style="display:inline-block;padding:13px 21px;background:#ff7a1a;border:1px solid #ff9b52;color:#160b04;border-radius:10px;font-weight:750;font-size:15px;line-height:1;text-decoration:none;box-shadow:0 10px 24px rgba(255,122,26,.2)">${label} →</a></div>`;
|
|
108
117
|
var VERSION = "0.1.0";
|
|
109
118
|
|
|
110
119
|
// src/notify-templates.ts
|
|
111
|
-
var FOOTER = "
|
|
120
|
+
var FOOTER = "You received this transactional security message because an action was requested for your account. If it was not you, do not share any code or approve the request.";
|
|
112
121
|
var signInCode = defineTemplate({
|
|
113
122
|
key: "auth.sign-in-code",
|
|
114
123
|
channel: "email",
|
|
@@ -116,12 +125,14 @@ var signInCode = defineTemplate({
|
|
|
116
125
|
data: ["code", "minutes"],
|
|
117
126
|
sample: { code: "418302", minutes: "10" },
|
|
118
127
|
subject: (data) => `${data.code} is your ForgeZero sign-in code`,
|
|
119
|
-
text: (data) => `${data.code} is your
|
|
128
|
+
text: (data) => `${data.code} is your ForgeZero verification code. It expires in ${data.minutes} minutes.
|
|
120
129
|
|
|
121
|
-
|
|
130
|
+
Enter it only in the ForgeZero window where you requested it. ForgeZero support will never ask for this code.
|
|
131
|
+
|
|
132
|
+
If you did not request it, ignore this email and review your active sessions.`,
|
|
122
133
|
html: (data) => layout({
|
|
123
134
|
title: "Your sign-in code",
|
|
124
|
-
body: codeBlock(data.code) + `<p style="margin:0">
|
|
135
|
+
body: codeBlock(data.code) + `<p style="margin:0;color:#f4f5f7">Enter this code only in the ForgeZero window where you requested it.</p>` + `<p style="margin:8px 0 0;color:#929aa7">It expires in ${data.minutes} minutes. ForgeZero support will never ask you to share it.</p>` + `<div style="margin:20px 0 0;padding:12px 14px;border:1px solid #3b414b;border-radius:9px;background:#101318;color:#929aa7;font-size:13px;line-height:1.55">Did not request this? Ignore the code and review your active sessions. No account change is completed by this email alone.</div>`,
|
|
125
136
|
footer: FOOTER
|
|
126
137
|
})
|
|
127
138
|
});
|
package/dist/notify.d.ts
CHANGED
|
@@ -165,6 +165,7 @@ export declare function layout(args: {
|
|
|
165
165
|
body: string;
|
|
166
166
|
footer?: string;
|
|
167
167
|
brand?: string;
|
|
168
|
+
preheader?: string;
|
|
168
169
|
}): string;
|
|
169
170
|
/** A code shown as digits a human can read aloud without losing their place. */
|
|
170
171
|
export declare const codeBlock: (code: string) => string;
|
package/dist/notify.js
CHANGED
|
@@ -88,23 +88,32 @@ function createNotifier(options) {
|
|
|
88
88
|
}
|
|
89
89
|
function layout(args) {
|
|
90
90
|
const brand = escapeHtml(args.brand ?? "ForgeZero");
|
|
91
|
+
const preheader = escapeHtml(args.preheader ?? `${args.title} — secure account notification`);
|
|
91
92
|
return `<!doctype html>
|
|
92
|
-
<html><
|
|
93
|
-
<
|
|
93
|
+
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="dark"><meta name="supported-color-schemes" content="dark"></head>
|
|
94
|
+
<body style="margin:0;padding:0;background:#090b0e;color:#f4f5f7;font-family:Inter,ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;-webkit-text-size-adjust:100%">
|
|
95
|
+
<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;line-height:1px;font-size:1px">${preheader} ‌ ‌ ‌ ‌</div>
|
|
96
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="width:100%;background:#090b0e;padding:48px 16px">
|
|
94
97
|
<tr><td align="center">
|
|
95
|
-
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:
|
|
96
|
-
<tr><td style="
|
|
97
|
-
<
|
|
98
|
-
<
|
|
98
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:580px;border-collapse:separate;background:#15181d;border:1px solid #30353d;border-radius:18px;box-shadow:0 24px 72px rgba(0,0,0,.42);overflow:hidden">
|
|
99
|
+
<tr><td style="height:3px;background:linear-gradient(90deg,#ff7a1a 0%,#ffb25c 38%,#30353d 38%);border-radius:18px 18px 0 0;font-size:0;line-height:0"> </td></tr>
|
|
100
|
+
<tr><td style="padding:28px 32px 12px">
|
|
101
|
+
<table role="presentation" width="100%" cellpadding="0" cellspacing="0"><tr>
|
|
102
|
+
<td valign="middle"><table role="presentation" cellpadding="0" cellspacing="0"><tr><td style="width:34px;height:34px;border:1px solid #5b3822;border-radius:10px;background:#20150e;text-align:center;color:#ff8b3d;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:16px;font-weight:800">FZ</td><td style="padding-left:11px;font-size:13px;font-weight:750;letter-spacing:.11em;text-transform:uppercase;color:#f4f5f7">${brand}</td></tr></table></td>
|
|
103
|
+
<td align="right" valign="middle"><span style="display:inline-block;padding:5px 8px;border:1px solid #394049;border-radius:999px;color:#9da5b2;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px;font-weight:700;letter-spacing:.1em;text-transform:uppercase">Protected message</span></td>
|
|
104
|
+
</tr></table>
|
|
105
|
+
<div style="margin-top:30px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:#ff8b3d">Account security</div>
|
|
106
|
+
<h1 style="margin:9px 0 0;font-size:26px;line-height:1.22;font-weight:700;letter-spacing:-.025em;color:#f7f8fa">${args.title}</h1>
|
|
99
107
|
</td></tr>
|
|
100
|
-
<tr><td style="padding:
|
|
108
|
+
<tr><td style="padding:14px 32px 30px;font-size:15px;line-height:1.65;color:#c8cdd6">${args.body}</td></tr>
|
|
109
|
+
<tr><td style="padding:15px 32px;border-top:1px solid #2a2f36;background:#111419;color:#7f8793;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;line-height:1.5;letter-spacing:.06em;text-transform:uppercase">Encrypted transport · Request-bound verification · No password</td></tr>
|
|
101
110
|
</table>
|
|
102
|
-
${args.footer ? `<
|
|
111
|
+
${args.footer ? `<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:580px"><tr><td style="padding:20px 18px 0;text-align:center;font-size:12px;line-height:1.6;color:#747c89">${args.footer}<br><span style="display:inline-block;margin-top:5px;color:#505762">ForgeZero · secure infrastructure control plane</span></td></tr></table>` : ""}
|
|
103
112
|
</td></tr></table>
|
|
104
113
|
</body></html>`;
|
|
105
114
|
}
|
|
106
|
-
var codeBlock = (code) => `<div style="margin:
|
|
107
|
-
var button = (label, href) => `<div style="margin:
|
|
115
|
+
var codeBlock = (code) => `<div style="margin:24px 0;padding:22px 16px;background:#0b0d10;border:1px solid #3b414b;border-radius:12px;text-align:center;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:32px;line-height:1;font-weight:750;letter-spacing:.32em;color:#ffffff;box-shadow:inset 3px 0 0 #ff7a1a,0 10px 28px rgba(0,0,0,.22)">${code}</div>`;
|
|
116
|
+
var button = (label, href) => `<div style="margin:26px 0"><a href="${href}" style="display:inline-block;padding:13px 21px;background:#ff7a1a;border:1px solid #ff9b52;color:#160b04;border-radius:10px;font-weight:750;font-size:15px;line-height:1;text-decoration:none;box-shadow:0 10px 24px rgba(255,122,26,.2)">${label} →</a></div>`;
|
|
108
117
|
var VERSION = "0.1.0";
|
|
109
118
|
export {
|
|
110
119
|
render,
|
package/dist/schema-typebox.js
CHANGED
|
@@ -141,6 +141,7 @@ function describeJsonSchema(schema, prefix = "") {
|
|
|
141
141
|
required: required.has(name),
|
|
142
142
|
description: property.description,
|
|
143
143
|
writeOnly: property.writeOnly === true ? true : undefined,
|
|
144
|
+
readOnly: property.readOnly === true ? true : undefined,
|
|
144
145
|
default: property.default,
|
|
145
146
|
format: property.format,
|
|
146
147
|
minLength: property.minLength,
|
|
@@ -181,6 +182,7 @@ function describeProperty(property, path, label, required) {
|
|
|
181
182
|
required,
|
|
182
183
|
description: property.description,
|
|
183
184
|
writeOnly: property.writeOnly === true ? true : undefined,
|
|
185
|
+
readOnly: property.readOnly === true ? true : undefined,
|
|
184
186
|
default: property.default,
|
|
185
187
|
format: property.format,
|
|
186
188
|
minLength: property.minLength,
|
package/dist/schema.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ export interface FormField {
|
|
|
61
61
|
* is what routes a credential into the vault instead of onto a page.
|
|
62
62
|
*/
|
|
63
63
|
writeOnly?: boolean;
|
|
64
|
+
/** Stored and validated, but supplied only by a trusted backend resolver. */
|
|
65
|
+
readOnly?: boolean;
|
|
64
66
|
default?: unknown;
|
|
65
67
|
/** `enum` only. */
|
|
66
68
|
options?: readonly string[];
|
package/dist/schema.js
CHANGED
|
@@ -141,6 +141,7 @@ function describeJsonSchema(schema, prefix = "") {
|
|
|
141
141
|
required: required.has(name),
|
|
142
142
|
description: property.description,
|
|
143
143
|
writeOnly: property.writeOnly === true ? true : undefined,
|
|
144
|
+
readOnly: property.readOnly === true ? true : undefined,
|
|
144
145
|
default: property.default,
|
|
145
146
|
format: property.format,
|
|
146
147
|
minLength: property.minLength,
|
|
@@ -181,6 +182,7 @@ function describeProperty(property, path, label, required) {
|
|
|
181
182
|
required,
|
|
182
183
|
description: property.description,
|
|
183
184
|
writeOnly: property.writeOnly === true ? true : undefined,
|
|
185
|
+
readOnly: property.readOnly === true ? true : undefined,
|
|
184
186
|
default: property.default,
|
|
185
187
|
format: property.format,
|
|
186
188
|
minLength: property.minLength,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgezero/runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
"prepublishOnly": "bun ../tools/package-task.ts prepublish runtime"
|
|
139
139
|
},
|
|
140
140
|
"dependencies": {
|
|
141
|
-
"@forgezero/access": "^0.1.
|
|
141
|
+
"@forgezero/access": "^0.1.14"
|
|
142
142
|
},
|
|
143
143
|
"peerDependencies": {
|
|
144
144
|
"@noble/ciphers": "^2.2.0",
|