diff --git a/app/lib/common-libs/errors.ts b/app/lib/common-libs/errors.ts
index 412c07ccd94c8fb5d6b6117af5bffab20a711a61..2e5798d1706032a440b2801faf0c49dd758a0e15 100755
--- a/app/lib/common-libs/errors.ts
+++ b/app/lib/common-libs/errors.ts
@@ -1,4 +1,7 @@
 export enum DataErrors {
+  TRANSACTION_WINDOW_IS_PASSED,
+  MEMBERSHIP_WINDOW_IS_PASSED,
+  CERT_WINDOW_IS_PASSED,
   INVALID_LEVELDB_IINDEX_DATA_WAS_KICKED,
   INVALID_LEVELDB_IINDEX_DATA_TO_BE_KICKED,
   IDENTITY_UID_NOT_FOUND,
diff --git a/app/lib/rules/global_rules.ts b/app/lib/rules/global_rules.ts
index 57721cfb1b7bfc6be0f7c18cc6c1da27815769f7..10ee6aca0cee501f60bab2013ae820e0add88ad1 100644
--- a/app/lib/rules/global_rules.ts
+++ b/app/lib/rules/global_rules.ts
@@ -24,6 +24,7 @@ import {hashf} from "../common"
 import {Indexer, SimpleTxInput} from "../indexer"
 import {DBTx} from "../db/DBTx"
 import {Tristamp} from "../common/Tristamp"
+import {DataErrors} from "../common-libs/errors"
 
 const constants      = CommonConstants
 
@@ -231,7 +232,7 @@ export const GLOBAL_RULES_HELPERS = {
     tx.blockstampTime = basedBlock.medianTime;
     const current = await dal.getCurrentBlockOrNull();
     if (current && current.medianTime > basedBlock.medianTime + constants.TX_WINDOW) {
-      throw "Transaction has expired";
+      throw DataErrors[DataErrors.TRANSACTION_WINDOW_IS_PASSED];
     }
   }
 }
diff --git a/app/service/MembershipService.ts b/app/service/MembershipService.ts
index 3dfe33fd6d9d27f261c30e088d34167539077795..a1cdaa8c5297f38e860063be2fe10e209bc0dfe5 100644
--- a/app/service/MembershipService.ts
+++ b/app/service/MembershipService.ts
@@ -20,6 +20,7 @@ import {GLOBAL_RULES_HELPERS} from "../lib/rules/global_rules";
 import {MembershipDTO} from "../lib/dto/MembershipDTO";
 import {FIFOService} from "./FIFOService";
 import {DBBlock} from "../lib/db/DBBlock"
+import {DataErrors} from "../lib/common-libs/errors"
 
 const constants       = require('../lib/constants');
 
@@ -75,6 +76,10 @@ export class MembershipService extends FIFOService {
         }, this.conf.pair && this.conf.pair.pub))) {
         throw constants.ERRORS.SANDBOX_FOR_MEMERSHIP_IS_FULL;
       }
+      const expires_on = basedBlock ? basedBlock.medianTime + this.conf.msWindow : 0
+      if (current && expires_on < current.medianTime) {
+        throw DataErrors[DataErrors.MEMBERSHIP_WINDOW_IS_PASSED]
+      }
       // Saves entry
       await this.dal.savePendingMembership({
         issuers: [entry.pubkey],
@@ -90,7 +95,7 @@ export class MembershipService extends FIFOService {
         idtyHash: entry.getIdtyHash(),
         written: false,
         written_number: null,
-        expires_on: basedBlock ? basedBlock.medianTime + this.conf.msWindow : 0,
+        expires_on,
         signature: entry.signature,
         expired: false,
         block_number: entry.number
diff --git a/test/integration/sandbox/expired-certifications.ts b/test/integration/sandbox/expired-certifications.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e3af0d5f5925bbfe8673db830a5f3b3147bbb075
--- /dev/null
+++ b/test/integration/sandbox/expired-certifications.ts
@@ -0,0 +1,63 @@
+// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
+// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+
+import {writeBasicTestWithConfAnd2Users} from "../tools/test-framework"
+import {assertThrows} from "../../unit-tools"
+import {CommonConstants} from "../../../app/lib/common-libs/constants"
+import {CertificationDTO} from "../../../app/lib/dto/CertificationDTO"
+
+describe('Expired certifications', () => writeBasicTestWithConfAnd2Users({
+  sigReplay: 3,
+  sigPeriod: 0,
+  sigValidity: 10,
+  sigWindow: 2, // <--- this is the important parameter for this test!
+}, (test) => {
+
+  before(() => {
+    CommonConstants.BLOCK_NEW_GENERATED_VERSION = 11
+  })
+
+  const now = 1500000000
+  let certToResend: CertificationDTO
+
+  test('should be able to init with 2 blocks', async (s1, cat, tac) => {
+    await cat.createIdentity()
+    await tac.createIdentity()
+    await cat.cert(tac)
+    await tac.cert(cat)
+    await cat.join()
+    await tac.join()
+    await s1.commit({ time: now, version: 10 })
+    await s1.commit({ time: now })
+  })
+
+  test('should accept toc, a new member at t+2', async (s1, cat, tac, toc) => {
+    await s1.commit({ time: now + 2 })
+    await s1.commit({ time: now + 2 })
+    await toc.createIdentity()
+    certToResend = await cat.makeCert(toc)
+    await cat.sendCert(certToResend)
+    await toc.join()
+    await s1.commit({ time: now + 2 })
+  })
+
+  test('should **NOT** be able to send again a written cert, even if replay time is passed', async (s1, cat, tac) => {
+    await s1.commit({ time: now + 6 })
+    await s1.commit({ time: now + 6 })
+    await assertThrows(cat.sendCert(certToResend), '{\n  "ucode": 1002,\n  "message": "CERT_WINDOW_IS_PASSED"\n}')
+  })
+
+  after(() => {
+    CommonConstants.BLOCK_NEW_GENERATED_VERSION = 10
+  })
+}))
diff --git a/test/integration/sandbox/expired-identity.ts b/test/integration/sandbox/expired-identity.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5d8af970213a677a3dfd133bdaf5e7bfdb36b5b9
--- /dev/null
+++ b/test/integration/sandbox/expired-identity.ts
@@ -0,0 +1,52 @@
+// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
+// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+
+import {writeBasicTestWithConfAnd2Users} from "../tools/test-framework"
+import {assertThrows} from "../../unit-tools"
+import {CommonConstants} from "../../../app/lib/common-libs/constants"
+
+describe('Expired identities', () => writeBasicTestWithConfAnd2Users({
+  sigReplay: 3,
+  sigPeriod: 0,
+  sigValidity: 10,
+  idtyWindow: 2, // <--- this is the important parameter for this test!
+}, (test) => {
+
+  before(() => {
+    CommonConstants.BLOCK_NEW_GENERATED_VERSION = 11
+  })
+
+  const now = 1500000000
+
+  test('should be able to init with 2 blocks', async (s1, cat, tac) => {
+    await cat.createIdentity()
+    await tac.createIdentity()
+    await cat.cert(tac)
+    await tac.cert(cat)
+    await cat.join()
+    await tac.join()
+    await s1.commit({ time: now, version: 10 })
+    await s1.commit({ time: now })
+  })
+
+  test('should **NOT** accept an expired identity', async (s1, cat, tac, toc) => {
+    const idty = await toc.makeIdentity()
+    await s1.commit({ time: now + 6 })
+    await s1.commit({ time: now + 6 })
+    await assertThrows(toc.submitIdentity(idty), '{\n  "ucode": 1002,\n  "message": "Identity is too old and cannot be written"\n}')
+  })
+
+  after(() => {
+    CommonConstants.BLOCK_NEW_GENERATED_VERSION = 10
+  })
+}))
diff --git a/test/integration/sandbox/expired-membership.ts b/test/integration/sandbox/expired-membership.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b98ebe3ab1517f805aa27881ea2aefa329581a00
--- /dev/null
+++ b/test/integration/sandbox/expired-membership.ts
@@ -0,0 +1,63 @@
+// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
+// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+
+import {writeBasicTestWithConfAnd2Users} from "../tools/test-framework"
+import {assertThrows} from "../../unit-tools"
+import {CommonConstants} from "../../../app/lib/common-libs/constants"
+
+describe('Expired membership', () => writeBasicTestWithConfAnd2Users({
+  sigReplay: 3,
+  sigPeriod: 0,
+  sigValidity: 10,
+  msWindow: 2, // <--- this is the important parameter for this test!
+}, (test) => {
+
+  before(() => {
+    CommonConstants.BLOCK_NEW_GENERATED_VERSION = 11
+  })
+
+  const now = 1500000000
+
+  test('should be able to init with 2 blocks', async (s1, cat, tac) => {
+    await cat.createIdentity()
+    await tac.createIdentity()
+    await cat.cert(tac)
+    await tac.cert(cat)
+    await cat.join()
+    await tac.join()
+    await s1.commit({ time: now, version: 10 })
+    await s1.commit({ time: now })
+  })
+
+  test('should accept toc, a new member at t+2', async (s1, cat, tac, toc) => {
+    await s1.commit({ time: now + 2 })
+    await s1.commit({ time: now + 2 })
+    await toc.createIdentity()
+    await cat.cert(toc)
+    await toc.join()
+    await s1.commit({ time: now + 2 })
+  })
+
+  test('should **NOT** be able to send an expired membership', async (s1, cat, tac, toc) => {
+    await s1.commit({ time: now + 3 })
+    await s1.commit({ time: now + 3 }) // <---- Time pass, so that the new membership becomes legit
+    const expiredMsAtTplus6 = await toc.makeMembership('IN')
+    await s1.commit({ time: now + 6 })
+    await s1.commit({ time: now + 6 }) // <---- But we want to make it expire
+    await assertThrows(toc.sendMembership(expiredMsAtTplus6), '{\n  "ucode": 1002,\n  "message": "MEMBERSHIP_WINDOW_IS_PASSED"\n}')
+  })
+
+  after(() => {
+    CommonConstants.BLOCK_NEW_GENERATED_VERSION = 10
+  })
+}))
diff --git a/test/integration/sandbox/expired-transactions.ts b/test/integration/sandbox/expired-transactions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fe950d99b375696770b013d6a3cd358e301f9688
--- /dev/null
+++ b/test/integration/sandbox/expired-transactions.ts
@@ -0,0 +1,54 @@
+// Source file from duniter: Crypto-currency software to manage libre currency such as Äž1
+// Copyright (C) 2018  Cedric Moreau <cem.moreau@gmail.com>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+
+import {writeBasicTestWithConfAnd2Users} from "../tools/test-framework"
+import {assertThrows} from "../../unit-tools"
+import {CommonConstants} from "../../../app/lib/common-libs/constants"
+
+describe('Expired transactions', () => writeBasicTestWithConfAnd2Users({
+  udTime0: 1500000000 - 1,
+}, (test) => {
+
+  let oldTxWindowValue: number
+
+  before(() => {
+    CommonConstants.BLOCK_NEW_GENERATED_VERSION = 11
+    oldTxWindowValue = CommonConstants.TX_WINDOW
+    CommonConstants.TX_WINDOW = 2 // We need a low value to pass time bounds rules
+  })
+
+  const now = 1500000000
+
+  test('should be able to init with 2 blocks', async (s1, cat, tac) => {
+    await cat.createIdentity()
+    await tac.createIdentity()
+    await cat.cert(tac)
+    await tac.cert(cat)
+    await cat.join()
+    await tac.join()
+    await s1.commit({ time: now, version: 10 })
+    await s1.commit({ time: now })
+  })
+
+  test('should **NOT** accept an expired transaction', async (s1, cat, tac, toc) => {
+    const rawTX = await cat.prepareITX(100, tac)
+    await s1.commit({ time: now + CommonConstants.TX_WINDOW + 1 })
+    await s1.commit({ time: now + CommonConstants.TX_WINDOW + 1 }) // <---- This is the important change! Make the TX expire
+    await assertThrows(toc.sendTX(rawTX), '{\n  "ucode": 1002,\n  "message": "TRANSACTION_WINDOW_IS_PASSED"\n}')
+  })
+
+  after(() => {
+    CommonConstants.BLOCK_NEW_GENERATED_VERSION = 10
+    CommonConstants.TX_WINDOW = oldTxWindowValue
+  })
+}))
diff --git a/test/integration/tools/TestUser.ts b/test/integration/tools/TestUser.ts
index 74941a78a7675e26ad6aee2bc43b1e42674cce31..cf25abe881bb9b9cf0d26129812cb1e5fc171cae 100644
--- a/test/integration/tools/TestUser.ts
+++ b/test/integration/tools/TestUser.ts
@@ -69,6 +69,11 @@ export class TestUser {
   }
 
   public async createIdentity(useRoot?:boolean|null, fromServer?:any) {
+    const idty = await this.makeIdentity(useRoot)
+    await this.submitIdentity(idty, fromServer);
+  }
+
+  public async makeIdentity(useRoot?:boolean|null) {
     if (!this.pub) {
       this.init(() => {})
     }
@@ -80,11 +85,10 @@ export class TestUser {
       issuer: this.pub,
       currency: this.node.server.conf.currency
     }).getRawUnSigned()
-    this.createdIdentity += KeyGen(this.pub, this.sec).signSync(this.createdIdentity) + '\n'
-    await this.submitIdentity(this.createdIdentity, fromServer);
+    return this.createdIdentity += KeyGen(this.pub, this.sec).signSync(this.createdIdentity) + '\n'
   }
 
-  public submitIdentity(raw:string, fromServer:any) {
+  public submitIdentity(raw:string, fromServer?: TestingServer) {
     return this.doPost('/wot/add', {
       "identity": raw
     }, fromServer)
@@ -118,17 +122,21 @@ export class TestUser {
 
   public async cert(user:TestUser, fromServer?:TestingServer, toServer?:TestingServer) {
     const cert = await this.makeCert(user, fromServer)
-    await this.doPost('/wot/certify', {
+    await this.sendCert(cert, toServer)
+  }
+
+  public async sendCert(cert: CertificationDTO, toServer?: TestingServer) {
+    return this.doPost('/wot/certify', {
       "cert": cert.getRawSigned()
-    }, toServer);
+    }, toServer)
   }
 
   public async join() {
-    return await this.sendMembership("IN")
+    return await this.publishMembership("IN")
   }
 
   public async leave() {
-    return await this.sendMembership("OUT")
+    return await this.publishMembership("OUT")
   }
 
   public async makeRevocation(givenLookupIdty?:HttpLookup, overrideProps?:any) {
@@ -181,11 +189,15 @@ export class TestUser {
     return MembershipDTO.fromJSONObject(join)
   }
 
-  public async sendMembership(type:string) {
+  public async publishMembership(type:string) {
     const ms = await this.makeMembership(type);
-    await this.post('/blockchain/membership', {
+    await this.sendMembership(ms)
+  }
+
+  public async sendMembership(ms: MembershipDTO, toServer?: TestingServer) {
+    return this.doPost('/blockchain/membership', {
       "membership": ms.getRawSigned()
-    })
+    }, toServer)
   }
 
   public async sendMoney(amount:number, recipient:TestUser, comment?:string) {
@@ -194,8 +206,7 @@ export class TestUser {
   }
 
   public async sendTX(rawTX:string) {
-    let http = await this.getContacter()
-    return http.processTransaction(rawTX)
+    return this.doPost('/tx/process', { transaction: rawTX })
   }
 
   public async prepareUTX(previousTX:string, unlocks:string[], outputs:TestOutput[], opts:any) {