Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ full engineering record.

## [Unreleased]

## [0.3.35] — 2026-08-01

- Gave a newly placed access petition a restrained violet-and-gold Hegemony
seal as it settles into its immediate Request Sent state.
- Kept the flourish outside layout and input handling, with no motion for
players who request reduced animation.
- Left previously recorded petitions quiet and non-clickable, with private
SpacetimeDB authority and manual admission unchanged.

## [0.3.34] — 2026-07-31

- Made Request Access become a disabled Request Sent action immediately after
Expand Down Expand Up @@ -380,7 +389,8 @@ full engineering record.
Lowlands, a first keep, Farcaster sign-in, and an admission-gated shared-world
foundation.

[Unreleased]: https://github.com/ael-dev3/Warpkeep/compare/v0.3.34...HEAD
[Unreleased]: https://github.com/ael-dev3/Warpkeep/compare/v0.3.35...HEAD
[0.3.35]: https://github.com/ael-dev3/Warpkeep/compare/v0.3.34...v0.3.35
[0.3.34]: https://github.com/ael-dev3/Warpkeep/compare/v0.3.33...v0.3.34
[0.3.33]: https://github.com/ael-dev3/Warpkeep/compare/v0.3.32...v0.3.33
[0.3.32]: https://github.com/ael-dev3/Warpkeep/compare/v0.3.31...v0.3.32
Expand Down
2 changes: 1 addition & 1 deletion docs/farcaster-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ordinary browsers use Sign In with Farcaster (SIWF), while a verified Farcaster
Mini App host may use Quick Auth. Neither path is a wallet connection,
client-owned identity, admission grant, or Terms acceptance.

Alpha 0.3.34 keeps backend protocol 3 and authentication contract v2; admission
Alpha 0.3.35 keeps backend protocol 3 and authentication contract v2; admission
remains gated. Production configuration and founder identities belong in the
private operator record, not this guide.

Expand Down
2 changes: 1 addition & 1 deletion docs/releases/versioning.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Versioning and releases

Warpkeep uses semantic versions for the product and Git commit SHAs for builds.
Alpha `0.3.34` is the live **The Petition Stands** release. A version is
Alpha `0.3.35` is the live **The Petition Is Sealed** release. A version is
described as live only after its protected review, matching client deployment,
and production smoke test all succeed.

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "warpkeep",
"private": true,
"version": "0.3.34",
"version": "0.3.35",
"description": "A Farcaster-connected persistent strategy world in active Alpha development.",
"license": "Apache-2.0",
"homepage": "https://warpkeep.com",
Expand Down
26 changes: 19 additions & 7 deletions src/components/auth/FarcasterAccessRequest.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Ref } from 'react';
import { useState, type Ref } from 'react';

import type { AccessRequestViewState } from '../../farcaster/farcasterAuthTypes';

Expand Down Expand Up @@ -93,6 +93,8 @@ export function FarcasterAccessRequestAction({
onRequestAccess,
primaryActionRef
}: FarcasterAccessRequestProps) {
const [requestCommittedLocally, setRequestCommittedLocally] = useState(false);

if (state.phase === 'idle' || state.phase === 'already-admitted') return null;

const isLoading = state.phase === 'loading';
Expand All @@ -106,17 +108,27 @@ export function FarcasterAccessRequestAction({
: isRequested
? 'REQUEST RECEIVED'
: 'REQUEST ACCESS';
const className = [
'farcaster-auth-panel__action',
accessRequestOwnsPrimaryAction(state)
? 'farcaster-auth-panel__action--primary'
: '',
requestCommittedLocally
? 'farcaster-auth-panel__action--request-committed'
: ''
].filter(Boolean).join(' ');

const handleRequestAccess = () => {
setRequestCommittedLocally(true);
onRequestAccess();
};

return (
<button
aria-label={label.replace('…', '')}
className={
accessRequestOwnsPrimaryAction(state)
? 'farcaster-auth-panel__action farcaster-auth-panel__action--primary'
: 'farcaster-auth-panel__action'
}
className={className}
disabled={disabled}
onClick={onRequestAccess}
onClick={handleRequestAccess}
ref={accessRequestAcceptsPrimaryFocus(state) ? primaryActionRef : undefined}
type="button"
>
Expand Down
44 changes: 44 additions & 0 deletions src/components/auth/FarcasterQrAuthPanel.css
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,23 @@
opacity: 0.48;
}

.farcaster-auth-panel__action--request-committed::before {
content: "";
position: absolute;
inset: -0.28rem;
border: 1px solid rgba(246, 214, 151, 0.96);
border-radius: calc(0.45rem + 0.28rem);
opacity: 0;
pointer-events: none;
box-shadow:
0 0 0 1px rgba(174, 94, 216, 0.82),
0 0 0.95rem rgba(158, 74, 205, 0.68),
inset 0 0 0.45rem rgba(238, 196, 119, 0.3);
transform: scale(0.97);
transform-origin: center;
animation: farcaster-auth-request-commit 1.15s cubic-bezier(0.16, 0.8, 0.22, 1) 1 both;
}

@media (hover: hover) and (pointer: fine) {
.farcaster-auth-panel__action:hover:not(:disabled) {
border-color: #d9ae68;
Expand Down Expand Up @@ -504,6 +521,28 @@ button.farcaster-identity-badge {
}
}

@keyframes farcaster-auth-request-commit {
0% {
opacity: 0;
transform: scale(0.97);
}

28% {
opacity: 1;
transform: scale(1.005);
}

62% {
opacity: 0.7;
transform: scale(1.022);
}

100% {
opacity: 0;
transform: scale(1.055);
}
}

@media (max-width: 600px), (orientation: portrait) {
.farcaster-auth-panel {
--farcaster-auth-qr-size: 190px;
Expand Down Expand Up @@ -622,4 +661,9 @@ button.farcaster-identity-badge {
.farcaster-auth-panel__action {
transition-duration: 1ms;
}

.farcaster-auth-panel__action--request-committed::before {
animation: none;
opacity: 0;
}
}
15 changes: 15 additions & 0 deletions src/components/menu/latestPatchNotes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ export type LatestPatchNotes = Readonly<{
alphaNotice: string;
}>;

const ALPHA_0_3_35_PATCH_NOTES: LatestPatchNotes = Object.freeze({
releasedOn: '1 AUG 2026',
title: 'THE PETITION IS SEALED',
summary:
'A violet-and-gold answer now gathers around a keeper’s petition the moment it leaves their hand.',
highlights: Object.freeze([
'Request Access answers the first click with a restrained Hegemony seal while the petition settles into its immediate Request Sent state.',
'The flourish never shifts the gateway or captures another touch, and it quiets completely when reduced motion is requested.',
'Only a newly placed petition receives the ceremony; an existing private Realm record remains calm, received, and impossible to submit again.'
]),
alphaNotice:
'Alpha 0.3.35 remains an invite-only, unfinished world. The seal confirms only that a petition was placed; it does not grant admission, create a keep, or change any Realm ownership or balance.'
});

const ALPHA_0_3_34_PATCH_NOTES: LatestPatchNotes = Object.freeze({
releasedOn: '31 JUL 2026',
title: 'THE PETITION STANDS',
Expand Down Expand Up @@ -247,6 +261,7 @@ const ALPHA_0_3_22_PATCH_NOTES: LatestPatchNotes = Object.freeze({

export const WARPKEEP_PATCH_NOTES_BY_VERSION: Readonly<Record<string, LatestPatchNotes>> =
Object.freeze({
'0.3.35': ALPHA_0_3_35_PATCH_NOTES,
'0.3.34': ALPHA_0_3_34_PATCH_NOTES,
'0.3.33': ALPHA_0_3_33_PATCH_NOTES,
'0.3.32': ALPHA_0_3_32_PATCH_NOTES,
Expand Down
4 changes: 2 additions & 2 deletions tests/buildInfo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ describe('Warpkeep build identity', () => {
);
});

it('reads the 0.3.34 product version from package metadata', () => {
it('reads the 0.3.35 product version from package metadata', () => {
const packageJson = JSON.parse(
readFileSync(resolve(process.cwd(), 'package.json'), 'utf8')
) as { version?: unknown };
const packageLock = JSON.parse(
readFileSync(resolve(process.cwd(), 'package-lock.json'), 'utf8')
) as { version?: unknown; packages?: Record<string, { version?: unknown }> };

expect(readWarpkeepProductVersion(packageJson.version)).toBe('0.3.34');
expect(readWarpkeepProductVersion(packageJson.version)).toBe('0.3.35');
expect(packageLock.version).toBe(packageJson.version);
expect(packageLock.packages?.['']?.version).toBe(packageJson.version);
expect(readWarpkeepProductVersion('1.0.0-alpha.1+build.7')).toBe('1.0.0-alpha.1+build.7');
Expand Down
9 changes: 9 additions & 0 deletions tests/farcasterAccessRequestLifecycle.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ describe('access-request controller lifecycle', () => {
expect(screen.getByText('submitting')).not.toBeNull();
const sent = screen.getByRole('button', { name: 'REQUEST SENT' }) as HTMLButtonElement;
expect(sent.disabled).toBe(true);
expect(sent.classList.contains(
'farcaster-auth-panel__action--request-committed'
)).toBe(true);
fireEvent.click(sent);
await waitFor(() => expect(requestAccess).toHaveBeenCalledTimes(1));

Expand All @@ -312,6 +315,9 @@ describe('access-request controller lifecycle', () => {
});
await waitFor(() => expect(screen.getByText('requested')).not.toBeNull());
expect(requestAccess).toHaveBeenCalledTimes(1);
expect(screen.getByRole('button', { name: 'REQUEST RECEIVED' }).classList.contains(
'farcaster-auth-panel__action--request-committed'
)).toBe(true);
});

it('never submits when SpacetimeDB already contains the current request', async () => {
Expand All @@ -331,6 +337,9 @@ describe('access-request controller lifecycle', () => {
name: 'REQUEST RECEIVED'
}) as HTMLButtonElement;
expect(received.disabled).toBe(true);
expect(received.classList.contains(
'farcaster-auth-panel__action--request-committed'
)).toBe(false);
fireEvent.click(received);
expect(requestAccess).not.toHaveBeenCalled();
});
Expand Down
14 changes: 9 additions & 5 deletions tests/latestPatchNotes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ describe('latest in-menu patch notes', () => {

expect(Object.keys(WARPKEEP_PATCH_NOTES_BY_VERSION)).toContain(packageJson.version);
expect(getLatestPatchNotes(packageJson.version)).toMatchObject({
releasedOn: '31 JUL 2026',
title: 'THE PETITION STANDS'
releasedOn: '1 AUG 2026',
title: 'THE PETITION IS SEALED'
});
expect(getLatestPatchNotes(packageJson.version)?.highlights.join(' ')).toMatch(
/Request Access.*disabled Request Sent.*first click.*without waiting/i
/Request Access.*first click.*Hegemony seal.*Request Sent/i
);
expect(getLatestPatchNotes(packageJson.version)?.highlights.join(' ')).toMatch(
/already recorded by SpacetimeDB.*received.*cannot be submitted again/i
/never shifts the gateway.*captures another touch.*reduced motion/i
);
expect(getLatestPatchNotes(packageJson.version)?.highlights.join(' ')).toMatch(
/repeated gestures.*absorbed locally.*cycle-idempotent.*manually reviewed/i
/newly placed petition.*existing private Realm record.*impossible to submit again/i
);
expect(getLatestPatchNotes(packageJson.version)?.highlights.join(' ')).not.toMatch(
/released to players|deployed to players|public balances|guaranteed rewards/i
Expand All @@ -38,6 +38,10 @@ describe('latest in-menu patch notes', () => {
'does not grant admission'
);

expect(getLatestPatchNotes('0.3.34')).toMatchObject({
title: 'THE PETITION STANDS'
});

const alpha033 = getLatestPatchNotes('0.3.33');
expect(alpha033).toMatchObject({
title: 'THE REALM REMEMBERS'
Expand Down
2 changes: 1 addition & 1 deletion tests/menuFarcasterAuthIntegration.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,7 @@ describe('WarpkeepMainMenu Farcaster authentication integration', () => {
'CREDITS'
]);
expect(screen.getByRole('button', {
name: 'Open patch notes for Warpkeep ALPHA 0.3.34'
name: 'Open patch notes for Warpkeep ALPHA 0.3.35'
})).not.toBeNull();

expect(screen.queryByRole('button', { name: 'CONTINUE' })).toBeNull();
Expand Down
Loading