Skip to content

Commit 494c024

Browse files
Merge branch 'aws:main' into claude/implement-blue-template-lKGq6
2 parents 1a14195 + b252095 commit 494c024

34 files changed

Lines changed: 2086 additions & 1672 deletions

plugins/aws-core/skills/aws-amplify/SKILL.md

Lines changed: 268 additions & 93 deletions
Large diffs are not rendered by default.

plugins/aws-core/skills/aws-amplify/references/ai.md

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
# AI
22

3+
> **Prerequisites:** Backend defined in `amplify/backend.ts` with `defineBackend({ auth, data })`.
4+
35
## Model Selection
46

57
Use `a.ai.model()` to select an AI model in both `a.conversation()` and `a.generation()` routes. Pass a human-readable model name string:
68

79
```typescript
8-
aiModel: a.ai.model('Claude 3.5 Sonnet v2')
10+
aiModel: a.ai.model('Claude Sonnet 4.5')
911
```
1012

11-
`a.ai.model()` accepts any supported model name:
13+
For the full list of supported models, see [AI Concepts: Models](https://docs.amplify.aws/react/ai/concepts/models/).
1214

13-
- **Anthropic**: `'Claude 3 Haiku'`, `'Claude 3 Sonnet'`, `'Claude 3 Opus'`, `'Claude 3.5 Haiku'`, `'Claude 3.5 Sonnet'`, `'Claude 3.5 Sonnet v2'`, `'Claude 3.7 Sonnet'`, `'Claude Opus 4'`, `'Claude Sonnet 4'`, `'Claude Haiku 4.5'`, `'Claude Sonnet 4.5'`, `'Claude Opus 4.5'`, `'Claude Sonnet 4.6'`, `'Claude Opus 4.6'`
14-
- **Amazon**: `'Amazon Nova Pro'`, `'Amazon Nova Lite'`, `'Amazon Nova Micro'`
15-
- **Meta**: `'Llama 3.1 405B Instruct'`, `'Llama 3.1 70B Instruct'`, `'Llama 3.1 8B Instruct'`
16-
- **Cohere**: `'Cohere Command R+'`, `'Cohere Command R'`
17-
- **Mistral**: `'Mistral Large 2'`, `'Mistral Large'`, `'Mistral Small'`
15+
Key constraint: `a.generation()` routes only support Anthropic (Claude) models. `a.conversation()` routes work with any supported model.
1816

1917
For models not in the supported list, use the raw escape hatch: `aiModel: { resourcePath: '<bedrock-model-id>' }`.
2018

2119
Availability depends on the AWS region and Bedrock model access enablement.
2220

23-
> **Note:** `a.generation()` routes only support Anthropic (Claude) models. `a.conversation()` routes work with any supported model.
21+
### Bedrock Model Access
22+
23+
Some older or restricted models require explicit enablement in the AWS Bedrock console (Model access). On-demand foundation models (Claude Sonnet 4+, Nova) are available immediately. Amplify uses global inference profiles for cross-region model access.
24+
25+
If you get `AccessDeniedException: Could not access the model with the specified model ID`, check **Bedrock → Model access** in your region.
2426

2527
## Backend: Conversation Routes
2628

@@ -33,7 +35,7 @@ import { a, type ClientSchema } from '@aws-amplify/backend';
3335

3436
const schema = a.schema({
3537
chat: a.conversation({
36-
aiModel: a.ai.model('Claude 3.5 Sonnet v2'),
38+
aiModel: a.ai.model('Claude Sonnet 4.5'),
3739
systemPrompt: 'You are a helpful assistant.',
3840
})
3941
.authorization(allow => allow.owner()),
@@ -44,12 +46,10 @@ const schema = a.schema({
4446

4547
Use `a.generation()` for single-turn (stateless) inference.
4648

47-
> **MUST:** Only Anthropic (Claude) models support `a.generation()` routes. Non-Anthropic models (Amazon Nova, Meta Llama, Cohere, Mistral) work with `a.conversation()` only.
48-
4949
```typescript
5050
const schema = a.schema({
5151
summarize: a.generation({
52-
aiModel: a.ai.model('Claude 3.5 Sonnet v2'),
52+
aiModel: a.ai.model('Claude Sonnet 4.5'),
5353
systemPrompt: 'Summarize the provided text concisely.',
5454
inferenceConfiguration: { maxTokens: 500, temperature: 0.3 },
5555
})
@@ -59,14 +59,16 @@ const schema = a.schema({
5959
});
6060
```
6161

62-
**CRITICAL — Authorization Constraints:**
62+
**Authorization constraints (these cause TypeError at CDK assembly if violated):**
6363

64-
- **Conversation routes** (`a.conversation()`) **MUST** use `allow.owner()` authorization — `allow.authenticated()` and other non-owner strategies throw a TypeError at CDK assembly time (before deployment even begins).
65-
- **Generation routes** (`a.generation()`) **MUST** use non-owner authorization (`allow.authenticated()`, `allow.guest()`, `allow.group()`, or `allow.publicApiKey()`) — `allow.owner()` throws a TypeError at CDK assembly time (before deployment even begins).
64+
- **Conversation routes** (`a.conversation()`) require `allow.owner()` authorization — `allow.authenticated()` and other non-owner strategies throw a TypeError at CDK assembly time.
65+
- **Generation routes** (`a.generation()`) require non-owner authorization (`allow.authenticated()`, `allow.guest()`, `allow.group()`, or `allow.publicApiKey()`) — `allow.owner()` throws a TypeError at CDK assembly time.
6666

6767
These constraints are asymmetric and frequently confused. Getting them wrong
6868
causes the CDK synthesis to fail with a non-obvious TypeError.
6969

70+
> **Security:** Conversation history sent to Amazon Bedrock may contain PII. Do not log full request/response payloads in production. Enable CloudWatch Logs encryption (KMS) and set appropriate retention policies for any logs that may capture inference data.
71+
7072
### Backend Integration
7173

7274
AI conversation and generation routes are part of your data schema. Import into `amplify/backend.ts`:
@@ -88,7 +90,7 @@ import { myToolFunc } from '../functions/my-tool/resource';
8890

8991
const schema = a.schema({
9092
chat: a.conversation({
91-
aiModel: a.ai.model('Claude 3.5 Sonnet v2'),
93+
aiModel: a.ai.model('Claude Sonnet 4.5'),
9294
systemPrompt: 'You are a helpful assistant with tool access.',
9395
tools: [
9496
{
@@ -170,7 +172,7 @@ Pagination: use `limit` and `nextToken` parameters on `.list()`.
170172

171173
Subscribe to streaming responses for real-time token delivery:
172174

173-
In React, **MUST** wrap in `useEffect` and return the cleanup function:
175+
In React, wrap in `useEffect` and return the cleanup function:
174176

175177
```tsx
176178
useEffect(() => {
@@ -189,18 +191,6 @@ useEffect(() => {
189191
190192
## Pitfalls
191193

192-
- **Conversation auth MUST be `allow.owner()`:** Using
193-
`allow.authenticated()` or any other non-owner strategy on
194-
`a.conversation()` throws a TypeError at CDK assembly time.
195-
- **Generation auth MUST NOT be `allow.owner()`:** Using
196-
`allow.owner()` on `a.generation()` throws a TypeError at CDK assembly
197-
time. Use `allow.authenticated()`, `allow.guest()`, or `allow.group()`.
198-
- **Missing AI route in data schema:** The conversation or generation
199-
route **MUST** be defined in your `a.schema()` — without it, the
200-
frontend client has no AI endpoint to call.
201-
- **Model availability:** Not all Bedrock models are enabled by default —
202-
you **MUST** enable model access in the AWS console (Bedrock → Model
203-
access) before using a model in `a.ai.model()`.
204194
- **Message content structure:** Both `sendMessage('Hello')` (string) and
205195
`sendMessage({ content: [{ text: 'Hello' }] })` (object) are valid. Use
206196
the object form when sending images or tool results.

plugins/aws-core/skills/aws-amplify/references/auth-backend.md

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Auth — Backend
22

3+
> **Prerequisites:** Backend defined in `amplify/backend.ts` with `defineBackend({ auth, data })`.
4+
35
## Basic Auth Setup
46

57
Define authentication in `amplify/auth/resource.ts`:
@@ -88,8 +90,8 @@ password-based login in the same `defineAuth` configuration.
8890

8991
## Social Login
9092

91-
You **MUST** use `secret()` for OAuth client secrets — never hardcode
92-
credentials.
93+
Use `secret()` for OAuth client secrets — hardcoding credentials exposes
94+
them in source control.
9395

9496
```typescript
9597
import { defineAuth, secret } from '@aws-amplify/backend';
@@ -122,27 +124,34 @@ export const auth = defineAuth({
122124
});
123125
```
124126

125-
Set secrets via CLI: `echo "<value>" | npx ampx sandbox secret set GOOGLE_CLIENT_ID`.
126-
For provider-specific OAuth setup guides, **SHOULD** consult AWS
127-
documentation via available tools; when unavailable, **MUST** use web
127+
Set secrets via CLI: `echo -n "<value>" | npx ampx sandbox secret set MY_OAUTH_CLIENT_ID`. (The documented approach uses an interactive prompt; piping with `echo -n` is a practical alternative for scripts.)
128+
For provider-specific OAuth setup guides, consult AWS
129+
documentation via available tools; when unavailable, use web
128130
search or AWS CLI.
129131

130132
## SAML / OIDC (Enterprise)
131133

132-
OIDC providers are configured directly in `externalProviders`:
134+
OIDC providers are configured inside `loginWith.externalProviders`:
133135

134136
```typescript
135-
externalProviders: {
136-
oidc: [{
137-
name: 'MyOIDC',
138-
clientId: secret('OIDC_CLIENT_ID'),
139-
clientSecret: secret('OIDC_CLIENT_SECRET'),
140-
issuerUrl: 'https://idp.example.com',
141-
attributeMapping: { email: 'email' },
142-
}],
143-
callbackUrls: ['http://localhost:3000/'],
144-
logoutUrls: ['http://localhost:3000/'],
145-
}
137+
import { defineAuth, secret } from '@aws-amplify/backend';
138+
139+
export const auth = defineAuth({
140+
loginWith: {
141+
email: true,
142+
externalProviders: {
143+
oidc: [{
144+
name: 'MyOIDC',
145+
clientId: secret('OIDC_CLIENT_ID'),
146+
clientSecret: secret('OIDC_CLIENT_SECRET'),
147+
issuerUrl: 'https://idp.example.com',
148+
attributeMapping: { email: 'email' },
149+
}],
150+
callbackUrls: ['http://localhost:3000/'],
151+
logoutUrls: ['http://localhost:3000/'],
152+
},
153+
},
154+
});
146155
```
147156

148157
**SAML** is NOT supported in `defineAuth` — the `ExternalProviderSpecificFactoryProps` type has no `saml` property. The lower-level `auth-construct` package supports SAML, but it was never wired up to the high-level API. Use CDK escape hatches via `backend.auth.resources` to configure SAML providers:
@@ -182,21 +191,51 @@ import { defineFunction } from '@aws-amplify/backend';
182191
export const preSignUp = defineFunction({ name: 'pre-sign-up' });
183192
```
184193

185-
### Guest (Unauthenticated) Access
194+
> **Tip:** Auth trigger handlers need `@types/aws-lambda` for TypeScript types.
195+
196+
### Trigger Lambda + Data Table Access
197+
198+
If a trigger Lambda (e.g., `postConfirmation`) needs to write to a `defineData` table, this can create a circular dependency. Workarounds:
199+
200+
1. **Access via `backend.auth.resources`** (avoids cycle when trigger is in auth stack):
201+
202+
```typescript
203+
// backend.ts
204+
const postConfirmFn = backend.auth.resources.userPool.triggers?.postConfirmation;
205+
const table = backend.data.resources.tables['UserProfile'];
206+
table.grantWriteData(postConfirmFn);
207+
postConfirmFn.addEnvironment('TABLE_NAME', table.tableName);
208+
```
209+
210+
1. **Separate DynamoDB table** — create via CDK (not `defineData`) to avoid stack coupling.
211+
212+
## Guest (Unauthenticated) Access
186213

187214
Guest access is **enabled by default** in Amplify Gen2 — the Cognito Identity Pool is created with `allowUnauthenticatedIdentities: true` automatically.
188215

189-
To use guest access in your data models, set `defaultAuthorizationMode` to `'iam'`:
216+
To use guest access in your data models, set `defaultAuthorizationMode` to `'iam'` and add `allow.guest()` authorization rules:
190217

191218
```typescript
219+
const schema = a.schema({
220+
Todo: a.model({
221+
content: a.string(),
222+
}).authorization(allow => [
223+
allow.guest().to(['read']), // unauthenticated users can read
224+
allow.owner(), // owners can CRUD
225+
]),
226+
});
227+
192228
export const data = defineData({
193229
schema,
194230
authorizationModes: {
195-
defaultAuthorizationMode: 'iam',
231+
defaultAuthorizationMode: 'iam', // required for guest access
232+
apiKeyAuthorizationMode: { expiresInDays: 7 }, // optional alternative
196233
},
197234
});
198235
```
199236

237+
> **Security:** Guest access grants unauthenticated users IAM-authorized access. For production, explicitly evaluate whether guest access is needed and prefer `allow.authenticated()` as the default. If guest access is required, scope it to read-only on non-sensitive models only.
238+
200239
To **disable** guest access, use a CDK override in `backend.ts`:
201240

202241
```typescript
@@ -208,8 +247,8 @@ cfnIdentityPool.allowUnauthenticatedIdentities = false;
208247

209248
- **Trigger not registered (silent no-op):** Defining a trigger function
210249
with `defineFunction` but NOT adding it to `triggers: {}` in `defineAuth`
211-
causes a **silent no-op** — the function deploys but never fires. You
212-
**MUST** both define AND register: `triggers: { preSignUp, postConfirmation }`.
250+
causes a **silent no-op** — the function deploys but never fires.
251+
Both define AND register: `triggers: { preSignUp, postConfirmation }`.
213252
- **Hardcoded secrets:** Using string literals instead of `secret()` for
214253
OAuth credentials exposes them in source control.
215254
- **Missing scopes:** Social providers default to minimal scopes — add
@@ -220,8 +259,9 @@ cfnIdentityPool.allowUnauthenticatedIdentities = false;
220259
- **MFA method mismatch:** Enabling `sms: true` in MFA requires a phone
221260
number attribute on the user pool — add `phone_number` to user attributes.
222261
Similarly, `email: true` in MFA requires an email attribute on the user pool.
223-
- **Secrets in CI/CD:** For branch environments, use:
224-
`npx ampx secret set KEY_NAME --branch main --app-id APP_ID`.
262+
- **Secrets in CI/CD:** For branch environments, manage secrets through the
263+
**Amplify console** (App settings → Environment variables → Secrets).
264+
The `ampx sandbox secret` command only works for local sandbox environments.
225265

226266
## Links
227267

0 commit comments

Comments
 (0)